diff --git a/packages/google-cloud-retail/docs/retail_v2/generative_question_service.rst b/packages/google-cloud-retail/docs/retail_v2/generative_question_service.rst new file mode 100644 index 000000000000..ff152eed1d0a --- /dev/null +++ b/packages/google-cloud-retail/docs/retail_v2/generative_question_service.rst @@ -0,0 +1,6 @@ +GenerativeQuestionService +------------------------------------------- + +.. automodule:: google.cloud.retail_v2.services.generative_question_service + :members: + :inherited-members: diff --git a/packages/google-cloud-retail/docs/retail_v2/services_.rst b/packages/google-cloud-retail/docs/retail_v2/services_.rst index 4cff46ae75f3..90d2a866505b 100644 --- a/packages/google-cloud-retail/docs/retail_v2/services_.rst +++ b/packages/google-cloud-retail/docs/retail_v2/services_.rst @@ -7,6 +7,7 @@ Services for Google Cloud Retail v2 API catalog_service completion_service control_service + generative_question_service model_service prediction_service product_service diff --git a/packages/google-cloud-retail/docs/retail_v2alpha/generative_question_service.rst b/packages/google-cloud-retail/docs/retail_v2alpha/generative_question_service.rst new file mode 100644 index 000000000000..4f986f0e3427 --- /dev/null +++ b/packages/google-cloud-retail/docs/retail_v2alpha/generative_question_service.rst @@ -0,0 +1,6 @@ +GenerativeQuestionService +------------------------------------------- + +.. automodule:: google.cloud.retail_v2alpha.services.generative_question_service + :members: + :inherited-members: diff --git a/packages/google-cloud-retail/docs/retail_v2alpha/services_.rst b/packages/google-cloud-retail/docs/retail_v2alpha/services_.rst index e553f71a69c2..b80c06573281 100644 --- a/packages/google-cloud-retail/docs/retail_v2alpha/services_.rst +++ b/packages/google-cloud-retail/docs/retail_v2alpha/services_.rst @@ -8,6 +8,7 @@ Services for Google Cloud Retail v2alpha API catalog_service completion_service control_service + generative_question_service merchant_center_account_link_service model_service prediction_service diff --git a/packages/google-cloud-retail/docs/retail_v2beta/generative_question_service.rst b/packages/google-cloud-retail/docs/retail_v2beta/generative_question_service.rst new file mode 100644 index 000000000000..3600d13144a1 --- /dev/null +++ b/packages/google-cloud-retail/docs/retail_v2beta/generative_question_service.rst @@ -0,0 +1,6 @@ +GenerativeQuestionService +------------------------------------------- + +.. automodule:: google.cloud.retail_v2beta.services.generative_question_service + :members: + :inherited-members: diff --git a/packages/google-cloud-retail/docs/retail_v2beta/project_service.rst b/packages/google-cloud-retail/docs/retail_v2beta/project_service.rst new file mode 100644 index 000000000000..ab53a010c63a --- /dev/null +++ b/packages/google-cloud-retail/docs/retail_v2beta/project_service.rst @@ -0,0 +1,6 @@ +ProjectService +-------------------------------- + +.. automodule:: google.cloud.retail_v2beta.services.project_service + :members: + :inherited-members: diff --git a/packages/google-cloud-retail/docs/retail_v2beta/services_.rst b/packages/google-cloud-retail/docs/retail_v2beta/services_.rst index ddcff7dff36c..1633ba7c7d7f 100644 --- a/packages/google-cloud-retail/docs/retail_v2beta/services_.rst +++ b/packages/google-cloud-retail/docs/retail_v2beta/services_.rst @@ -7,9 +7,11 @@ Services for Google Cloud Retail v2beta API catalog_service completion_service control_service + generative_question_service model_service prediction_service product_service + project_service search_service serving_config_service user_event_service diff --git a/packages/google-cloud-retail/google/cloud/retail/__init__.py b/packages/google-cloud-retail/google/cloud/retail/__init__.py index 4ab2ad33dce8..f0ffab85cbe8 100644 --- a/packages/google-cloud-retail/google/cloud/retail/__init__.py +++ b/packages/google-cloud-retail/google/cloud/retail/__init__.py @@ -38,6 +38,12 @@ ControlServiceAsyncClient, ) from google.cloud.retail_v2.services.control_service.client import ControlServiceClient +from google.cloud.retail_v2.services.generative_question_service.async_client import ( + GenerativeQuestionServiceAsyncClient, +) +from google.cloud.retail_v2.services.generative_question_service.client import ( + GenerativeQuestionServiceClient, +) from google.cloud.retail_v2.services.model_service.async_client import ( ModelServiceAsyncClient, ) @@ -131,6 +137,19 @@ OutputConfig, OutputResult, ) +from google.cloud.retail_v2.types.generative_question import ( + GenerativeQuestionConfig, + GenerativeQuestionsFeatureConfig, +) +from google.cloud.retail_v2.types.generative_question_service import ( + BatchUpdateGenerativeQuestionConfigsRequest, + BatchUpdateGenerativeQuestionConfigsResponse, + GetGenerativeQuestionsFeatureConfigRequest, + ListGenerativeQuestionConfigsRequest, + ListGenerativeQuestionConfigsResponse, + UpdateGenerativeQuestionConfigRequest, + UpdateGenerativeQuestionsFeatureConfigRequest, +) from google.cloud.retail_v2.types.import_config import ( BigQuerySource, CompletionDataInputConfig, @@ -203,8 +222,11 @@ ) from google.cloud.retail_v2.types.search_service import ( ExperimentInfo, + ProductAttributeInterval, + ProductAttributeValue, SearchRequest, SearchResponse, + Tile, ) from google.cloud.retail_v2.types.serving_config import ServingConfig from google.cloud.retail_v2.types.serving_config_service import ( @@ -240,6 +262,8 @@ "CompletionServiceAsyncClient", "ControlServiceClient", "ControlServiceAsyncClient", + "GenerativeQuestionServiceClient", + "GenerativeQuestionServiceAsyncClient", "ModelServiceClient", "ModelServiceAsyncClient", "PredictionServiceClient", @@ -303,6 +327,15 @@ "GcsOutputResult", "OutputConfig", "OutputResult", + "GenerativeQuestionConfig", + "GenerativeQuestionsFeatureConfig", + "BatchUpdateGenerativeQuestionConfigsRequest", + "BatchUpdateGenerativeQuestionConfigsResponse", + "GetGenerativeQuestionsFeatureConfigRequest", + "ListGenerativeQuestionConfigsRequest", + "ListGenerativeQuestionConfigsResponse", + "UpdateGenerativeQuestionConfigRequest", + "UpdateGenerativeQuestionsFeatureConfigRequest", "BigQuerySource", "CompletionDataInputConfig", "GcsSource", @@ -364,8 +397,11 @@ "PurgeUserEventsRequest", "PurgeUserEventsResponse", "ExperimentInfo", + "ProductAttributeInterval", + "ProductAttributeValue", "SearchRequest", "SearchResponse", + "Tile", "ServingConfig", "AddControlRequest", "CreateServingConfigRequest", diff --git a/packages/google-cloud-retail/google/cloud/retail_v2/__init__.py b/packages/google-cloud-retail/google/cloud/retail_v2/__init__.py index b15ab210720f..cc13ec260e1a 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2/__init__.py +++ b/packages/google-cloud-retail/google/cloud/retail_v2/__init__.py @@ -28,6 +28,10 @@ CompletionServiceClient, ) from .services.control_service import ControlServiceAsyncClient, ControlServiceClient +from .services.generative_question_service import ( + GenerativeQuestionServiceAsyncClient, + GenerativeQuestionServiceClient, +) from .services.model_service import ModelServiceAsyncClient, ModelServiceClient from .services.prediction_service import ( PredictionServiceAsyncClient, @@ -103,6 +107,19 @@ OutputConfig, OutputResult, ) +from .types.generative_question import ( + GenerativeQuestionConfig, + GenerativeQuestionsFeatureConfig, +) +from .types.generative_question_service import ( + BatchUpdateGenerativeQuestionConfigsRequest, + BatchUpdateGenerativeQuestionConfigsResponse, + GetGenerativeQuestionsFeatureConfigRequest, + ListGenerativeQuestionConfigsRequest, + ListGenerativeQuestionConfigsResponse, + UpdateGenerativeQuestionConfigRequest, + UpdateGenerativeQuestionsFeatureConfigRequest, +) from .types.import_config import ( BigQuerySource, CompletionDataInputConfig, @@ -170,7 +187,14 @@ PurgeUserEventsRequest, PurgeUserEventsResponse, ) -from .types.search_service import ExperimentInfo, SearchRequest, SearchResponse +from .types.search_service import ( + ExperimentInfo, + ProductAttributeInterval, + ProductAttributeValue, + SearchRequest, + SearchResponse, + Tile, +) from .types.serving_config import ServingConfig from .types.serving_config_service import ( AddControlRequest, @@ -201,6 +225,7 @@ "CatalogServiceAsyncClient", "CompletionServiceAsyncClient", "ControlServiceAsyncClient", + "GenerativeQuestionServiceAsyncClient", "ModelServiceAsyncClient", "PredictionServiceAsyncClient", "ProductServiceAsyncClient", @@ -219,6 +244,8 @@ "AttributeConfigLevel", "AttributesConfig", "Audience", + "BatchUpdateGenerativeQuestionConfigsRequest", + "BatchUpdateGenerativeQuestionConfigsResponse", "BigQueryOutputResult", "BigQuerySource", "Catalog", @@ -253,11 +280,15 @@ "FulfillmentInfo", "GcsOutputResult", "GcsSource", + "GenerativeQuestionConfig", + "GenerativeQuestionServiceClient", + "GenerativeQuestionsFeatureConfig", "GetAttributesConfigRequest", "GetCompletionConfigRequest", "GetControlRequest", "GetDefaultBranchRequest", "GetDefaultBranchResponse", + "GetGenerativeQuestionsFeatureConfigRequest", "GetModelRequest", "GetProductRequest", "GetServingConfigRequest", @@ -275,6 +306,8 @@ "ListCatalogsResponse", "ListControlsRequest", "ListControlsResponse", + "ListGenerativeQuestionConfigsRequest", + "ListGenerativeQuestionConfigsResponse", "ListModelsRequest", "ListModelsResponse", "ListProductsRequest", @@ -292,6 +325,8 @@ "PredictionServiceClient", "PriceInfo", "Product", + "ProductAttributeInterval", + "ProductAttributeValue", "ProductDetail", "ProductInlineSource", "ProductInputConfig", @@ -332,6 +367,7 @@ "SetInventoryRequest", "SetInventoryResponse", "SolutionType", + "Tile", "TuneModelMetadata", "TuneModelRequest", "TuneModelResponse", @@ -339,6 +375,8 @@ "UpdateCatalogRequest", "UpdateCompletionConfigRequest", "UpdateControlRequest", + "UpdateGenerativeQuestionConfigRequest", + "UpdateGenerativeQuestionsFeatureConfigRequest", "UpdateModelRequest", "UpdateProductRequest", "UpdateServingConfigRequest", diff --git a/packages/google-cloud-retail/google/cloud/retail_v2/gapic_metadata.json b/packages/google-cloud-retail/google/cloud/retail_v2/gapic_metadata.json index f9d0979e7517..29426c7e7974 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2/gapic_metadata.json +++ b/packages/google-cloud-retail/google/cloud/retail_v2/gapic_metadata.json @@ -366,6 +366,100 @@ } } }, + "GenerativeQuestionService": { + "clients": { + "grpc": { + "libraryClient": "GenerativeQuestionServiceClient", + "rpcs": { + "BatchUpdateGenerativeQuestionConfigs": { + "methods": [ + "batch_update_generative_question_configs" + ] + }, + "GetGenerativeQuestionsFeatureConfig": { + "methods": [ + "get_generative_questions_feature_config" + ] + }, + "ListGenerativeQuestionConfigs": { + "methods": [ + "list_generative_question_configs" + ] + }, + "UpdateGenerativeQuestionConfig": { + "methods": [ + "update_generative_question_config" + ] + }, + "UpdateGenerativeQuestionsFeatureConfig": { + "methods": [ + "update_generative_questions_feature_config" + ] + } + } + }, + "grpc-async": { + "libraryClient": "GenerativeQuestionServiceAsyncClient", + "rpcs": { + "BatchUpdateGenerativeQuestionConfigs": { + "methods": [ + "batch_update_generative_question_configs" + ] + }, + "GetGenerativeQuestionsFeatureConfig": { + "methods": [ + "get_generative_questions_feature_config" + ] + }, + "ListGenerativeQuestionConfigs": { + "methods": [ + "list_generative_question_configs" + ] + }, + "UpdateGenerativeQuestionConfig": { + "methods": [ + "update_generative_question_config" + ] + }, + "UpdateGenerativeQuestionsFeatureConfig": { + "methods": [ + "update_generative_questions_feature_config" + ] + } + } + }, + "rest": { + "libraryClient": "GenerativeQuestionServiceClient", + "rpcs": { + "BatchUpdateGenerativeQuestionConfigs": { + "methods": [ + "batch_update_generative_question_configs" + ] + }, + "GetGenerativeQuestionsFeatureConfig": { + "methods": [ + "get_generative_questions_feature_config" + ] + }, + "ListGenerativeQuestionConfigs": { + "methods": [ + "list_generative_question_configs" + ] + }, + "UpdateGenerativeQuestionConfig": { + "methods": [ + "update_generative_question_config" + ] + }, + "UpdateGenerativeQuestionsFeatureConfig": { + "methods": [ + "update_generative_questions_feature_config" + ] + } + } + } + } + }, "ModelService": { "clients": { "grpc": { diff --git a/packages/google-cloud-retail/google/cloud/retail_v2/services/generative_question_service/__init__.py b/packages/google-cloud-retail/google/cloud/retail_v2/services/generative_question_service/__init__.py new file mode 100644 index 000000000000..f9196ca8080a --- /dev/null +++ b/packages/google-cloud-retail/google/cloud/retail_v2/services/generative_question_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from .async_client import GenerativeQuestionServiceAsyncClient +from .client import GenerativeQuestionServiceClient + +__all__ = ( + "GenerativeQuestionServiceClient", + "GenerativeQuestionServiceAsyncClient", +) diff --git a/packages/google-cloud-retail/google/cloud/retail_v2/services/generative_question_service/async_client.py b/packages/google-cloud-retail/google/cloud/retail_v2/services/generative_question_service/async_client.py new file mode 100644 index 000000000000..a2ebf9328e94 --- /dev/null +++ b/packages/google-cloud-retail/google/cloud/retail_v2/services/generative_question_service/async_client.py @@ -0,0 +1,1060 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import re +from typing import ( + Callable, + Dict, + Mapping, + MutableMapping, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, +) + +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.api_core.client_options import ClientOptions +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.cloud.retail_v2 import gapic_version as package_version + +try: + OptionalRetry = Union[retries.AsyncRetry, gapic_v1.method._MethodDefault, None] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.AsyncRetry, object, None] # type: ignore + +from google.cloud.location import locations_pb2 # type: ignore +from google.longrunning import operations_pb2 # type: ignore +from google.protobuf import field_mask_pb2 # type: ignore + +from google.cloud.retail_v2.types import ( + generative_question, + generative_question_service, +) + +from .client import GenerativeQuestionServiceClient +from .transports.base import DEFAULT_CLIENT_INFO, GenerativeQuestionServiceTransport +from .transports.grpc_asyncio import GenerativeQuestionServiceGrpcAsyncIOTransport + + +class GenerativeQuestionServiceAsyncClient: + """Service for managing LLM generated questions in search + serving. + """ + + _client: GenerativeQuestionServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = GenerativeQuestionServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = GenerativeQuestionServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + GenerativeQuestionServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = GenerativeQuestionServiceClient._DEFAULT_UNIVERSE + + catalog_path = staticmethod(GenerativeQuestionServiceClient.catalog_path) + parse_catalog_path = staticmethod( + GenerativeQuestionServiceClient.parse_catalog_path + ) + common_billing_account_path = staticmethod( + GenerativeQuestionServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + GenerativeQuestionServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + GenerativeQuestionServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + GenerativeQuestionServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + GenerativeQuestionServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + GenerativeQuestionServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + GenerativeQuestionServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + GenerativeQuestionServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + GenerativeQuestionServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + GenerativeQuestionServiceClient.parse_common_location_path + ) + + @classmethod + def from_service_account_info(cls, info: dict, *args, **kwargs): + """Creates an instance of this client using the provided credentials + info. + + Args: + info (dict): The service account private key info. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + GenerativeQuestionServiceAsyncClient: The constructed client. + """ + return GenerativeQuestionServiceClient.from_service_account_info.__func__(GenerativeQuestionServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + GenerativeQuestionServiceAsyncClient: The constructed client. + """ + return GenerativeQuestionServiceClient.from_service_account_file.__func__(GenerativeQuestionServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return GenerativeQuestionServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> GenerativeQuestionServiceTransport: + """Returns the transport used by the client instance. + + Returns: + GenerativeQuestionServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = GenerativeQuestionServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + GenerativeQuestionServiceTransport, + Callable[..., GenerativeQuestionServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the generative question service async client. + + Args: + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + transport (Optional[Union[str,GenerativeQuestionServiceTransport,Callable[..., GenerativeQuestionServiceTransport]]]): + The transport to use, or a Callable that constructs and returns a new transport to use. + If a Callable is given, it will be called with the same set of initialization + arguments as used in the GenerativeQuestionServiceTransport constructor. + If set to None, a transport is chosen automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): + Custom options for the client. + + 1. The ``api_endpoint`` property can be used to override the + default endpoint provided by the client when ``transport`` is + not explicitly provided. Only if this property is not set and + ``transport`` was not explicitly provided, the endpoint is + determined by the GOOGLE_API_USE_MTLS_ENDPOINT environment + variable, which have one of the following values: + "always" (always use the default mTLS endpoint), "never" (always + use the default regular endpoint) and "auto" (auto-switch to the + default mTLS endpoint if client certificate is present; this is + the default value). + + 2. If the GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide a client certificate for mTLS transport. If + not provided, the default SSL client certificate will be used if + present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not + set, no client certificate will be used. + + 3. The ``universe_domain`` property can be used to override the + default "googleapis.com" universe. Note that ``api_endpoint`` + property still takes precedence; and ``universe_domain`` is + currently not supported for mTLS. + + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + + Raises: + google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport + creation failed for any reason. + """ + self._client = GenerativeQuestionServiceClient( + credentials=credentials, + transport=transport, + client_options=client_options, + client_info=client_info, + ) + + async def update_generative_questions_feature_config( + self, + request: Optional[ + Union[ + generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest, + dict, + ] + ] = None, + *, + generative_questions_feature_config: Optional[ + generative_question.GenerativeQuestionsFeatureConfig + ] = None, + update_mask: Optional[field_mask_pb2.FieldMask] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> generative_question.GenerativeQuestionsFeatureConfig: + r"""Manages overal generative question feature state -- + enables toggling feature on and off. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import retail_v2 + + async def sample_update_generative_questions_feature_config(): + # Create a client + client = retail_v2.GenerativeQuestionServiceAsyncClient() + + # Initialize request argument(s) + generative_questions_feature_config = retail_v2.GenerativeQuestionsFeatureConfig() + generative_questions_feature_config.catalog = "catalog_value" + + request = retail_v2.UpdateGenerativeQuestionsFeatureConfigRequest( + generative_questions_feature_config=generative_questions_feature_config, + ) + + # Make the request + response = await client.update_generative_questions_feature_config(request=request) + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.retail_v2.types.UpdateGenerativeQuestionsFeatureConfigRequest, dict]]): + The request object. Request for + UpdateGenerativeQuestionsFeatureConfig + method. + generative_questions_feature_config (:class:`google.cloud.retail_v2.types.GenerativeQuestionsFeatureConfig`): + Required. The configuration managing + the feature state. + + This corresponds to the ``generative_questions_feature_config`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + update_mask (:class:`google.protobuf.field_mask_pb2.FieldMask`): + Optional. Indicates which fields in the provided + [GenerativeQuestionsFeatureConfig][google.cloud.retail.v2.GenerativeQuestionsFeatureConfig] + to update. If not set or empty, all supported fields are + updated. + + This corresponds to the ``update_mask`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry_async.AsyncRetry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.retail_v2.types.GenerativeQuestionsFeatureConfig: + Configuration for overall generative + question feature state. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([generative_questions_feature_config, update_mask]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance( + request, + generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest, + ): + request = generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if generative_questions_feature_config is not None: + request.generative_questions_feature_config = ( + generative_questions_feature_config + ) + if update_mask is not None: + request.update_mask = update_mask + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.update_generative_questions_feature_config + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + ( + ( + "generative_questions_feature_config.catalog", + request.generative_questions_feature_config.catalog, + ), + ) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def get_generative_questions_feature_config( + self, + request: Optional[ + Union[ + generative_question_service.GetGenerativeQuestionsFeatureConfigRequest, + dict, + ] + ] = None, + *, + catalog: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> generative_question.GenerativeQuestionsFeatureConfig: + r"""Manages overal generative question feature state -- + enables toggling feature on and off. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import retail_v2 + + async def sample_get_generative_questions_feature_config(): + # Create a client + client = retail_v2.GenerativeQuestionServiceAsyncClient() + + # Initialize request argument(s) + request = retail_v2.GetGenerativeQuestionsFeatureConfigRequest( + catalog="catalog_value", + ) + + # Make the request + response = await client.get_generative_questions_feature_config(request=request) + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.retail_v2.types.GetGenerativeQuestionsFeatureConfigRequest, dict]]): + The request object. Request for + GetGenerativeQuestionsFeatureConfig + method. + catalog (:class:`str`): + Required. Resource name of the parent + catalog. Format: + projects/{project}/locations/{location}/catalogs/{catalog} + + This corresponds to the ``catalog`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry_async.AsyncRetry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.retail_v2.types.GenerativeQuestionsFeatureConfig: + Configuration for overall generative + question feature state. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([catalog]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance( + request, + generative_question_service.GetGenerativeQuestionsFeatureConfigRequest, + ): + request = ( + generative_question_service.GetGenerativeQuestionsFeatureConfigRequest( + request + ) + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if catalog is not None: + request.catalog = catalog + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.get_generative_questions_feature_config + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("catalog", request.catalog),)), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def list_generative_question_configs( + self, + request: Optional[ + Union[ + generative_question_service.ListGenerativeQuestionConfigsRequest, dict + ] + ] = None, + *, + parent: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> generative_question_service.ListGenerativeQuestionConfigsResponse: + r"""Returns all questions for a given catalog. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import retail_v2 + + async def sample_list_generative_question_configs(): + # Create a client + client = retail_v2.GenerativeQuestionServiceAsyncClient() + + # Initialize request argument(s) + request = retail_v2.ListGenerativeQuestionConfigsRequest( + parent="parent_value", + ) + + # Make the request + response = await client.list_generative_question_configs(request=request) + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.retail_v2.types.ListGenerativeQuestionConfigsRequest, dict]]): + The request object. Request for ListQuestions method. + parent (:class:`str`): + Required. Resource name of the parent + catalog. Format: + projects/{project}/locations/{location}/catalogs/{catalog} + + This corresponds to the ``parent`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry_async.AsyncRetry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.retail_v2.types.ListGenerativeQuestionConfigsResponse: + Response for ListQuestions method. + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([parent]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance( + request, generative_question_service.ListGenerativeQuestionConfigsRequest + ): + request = generative_question_service.ListGenerativeQuestionConfigsRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if parent is not None: + request.parent = parent + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.list_generative_question_configs + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def update_generative_question_config( + self, + request: Optional[ + Union[ + generative_question_service.UpdateGenerativeQuestionConfigRequest, dict + ] + ] = None, + *, + generative_question_config: Optional[ + generative_question.GenerativeQuestionConfig + ] = None, + update_mask: Optional[field_mask_pb2.FieldMask] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> generative_question.GenerativeQuestionConfig: + r"""Allows management of individual questions. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import retail_v2 + + async def sample_update_generative_question_config(): + # Create a client + client = retail_v2.GenerativeQuestionServiceAsyncClient() + + # Initialize request argument(s) + generative_question_config = retail_v2.GenerativeQuestionConfig() + generative_question_config.catalog = "catalog_value" + generative_question_config.facet = "facet_value" + + request = retail_v2.UpdateGenerativeQuestionConfigRequest( + generative_question_config=generative_question_config, + ) + + # Make the request + response = await client.update_generative_question_config(request=request) + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.retail_v2.types.UpdateGenerativeQuestionConfigRequest, dict]]): + The request object. Request for + UpdateGenerativeQuestionConfig method. + generative_question_config (:class:`google.cloud.retail_v2.types.GenerativeQuestionConfig`): + Required. The question to update. + This corresponds to the ``generative_question_config`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + update_mask (:class:`google.protobuf.field_mask_pb2.FieldMask`): + Optional. Indicates which fields in the provided + [GenerativeQuestionConfig][google.cloud.retail.v2.GenerativeQuestionConfig] + to update. The following are NOT supported: + + - [GenerativeQuestionConfig.frequency][google.cloud.retail.v2.GenerativeQuestionConfig.frequency] + + If not set or empty, all supported fields are updated. + + This corresponds to the ``update_mask`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry_async.AsyncRetry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.retail_v2.types.GenerativeQuestionConfig: + Configuration for a single generated + question. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([generative_question_config, update_mask]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance( + request, generative_question_service.UpdateGenerativeQuestionConfigRequest + ): + request = generative_question_service.UpdateGenerativeQuestionConfigRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if generative_question_config is not None: + request.generative_question_config = generative_question_config + if update_mask is not None: + request.update_mask = update_mask + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.update_generative_question_config + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + ( + ( + "generative_question_config.catalog", + request.generative_question_config.catalog, + ), + ) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def batch_update_generative_question_configs( + self, + request: Optional[ + Union[ + generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest, + dict, + ] + ] = None, + *, + parent: Optional[str] = None, + requests: Optional[ + MutableSequence[ + generative_question_service.UpdateGenerativeQuestionConfigRequest + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse: + r"""Allows management of multiple questions. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import retail_v2 + + async def sample_batch_update_generative_question_configs(): + # Create a client + client = retail_v2.GenerativeQuestionServiceAsyncClient() + + # Initialize request argument(s) + requests = retail_v2.UpdateGenerativeQuestionConfigRequest() + requests.generative_question_config.catalog = "catalog_value" + requests.generative_question_config.facet = "facet_value" + + request = retail_v2.BatchUpdateGenerativeQuestionConfigsRequest( + requests=requests, + ) + + # Make the request + response = await client.batch_update_generative_question_configs(request=request) + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.retail_v2.types.BatchUpdateGenerativeQuestionConfigsRequest, dict]]): + The request object. Request for + BatchUpdateGenerativeQuestionConfig + method. + parent (:class:`str`): + Optional. Resource name of the parent + catalog. Format: + projects/{project}/locations/{location}/catalogs/{catalog} + + This corresponds to the ``parent`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + requests (:class:`MutableSequence[google.cloud.retail_v2.types.UpdateGenerativeQuestionConfigRequest]`): + Required. The updates question + configs. + + This corresponds to the ``requests`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry_async.AsyncRetry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.retail_v2.types.BatchUpdateGenerativeQuestionConfigsResponse: + Aggregated response for + UpdateGenerativeQuestionConfig method. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([parent, requests]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance( + request, + generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest, + ): + request = ( + generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest( + request + ) + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if parent is not None: + request.parent = parent + if requests: + request.requests.extend(requests) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.batch_update_generative_question_configs + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def list_operations( + self, + request: Optional[operations_pb2.ListOperationsRequest] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operations_pb2.ListOperationsResponse: + r"""Lists operations that match the specified filter in the request. + + Args: + request (:class:`~.operations_pb2.ListOperationsRequest`): + The request object. Request message for + `ListOperations` method. + retry (google.api_core.retry_async.AsyncRetry): Designation of what errors, + if any, should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + Returns: + ~.operations_pb2.ListOperationsResponse: + Response message for ``ListOperations`` method. + """ + # Create or coerce a protobuf request object. + # The request isn't a proto-plus wrapped type, + # so it must be constructed via keyword expansion. + if isinstance(request, dict): + request = operations_pb2.ListOperationsRequest(**request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method_async.wrap_method( + self._client._transport.list_operations, + default_timeout=None, + client_info=DEFAULT_CLIENT_INFO, + ) + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def get_operation( + self, + request: Optional[operations_pb2.GetOperationRequest] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operations_pb2.Operation: + r"""Gets the latest state of a long-running operation. + + Args: + request (:class:`~.operations_pb2.GetOperationRequest`): + The request object. Request message for + `GetOperation` method. + retry (google.api_core.retry_async.AsyncRetry): Designation of what errors, + if any, should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + Returns: + ~.operations_pb2.Operation: + An ``Operation`` object. + """ + # Create or coerce a protobuf request object. + # The request isn't a proto-plus wrapped type, + # so it must be constructed via keyword expansion. + if isinstance(request, dict): + request = operations_pb2.GetOperationRequest(**request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method_async.wrap_method( + self._client._transport.get_operation, + default_timeout=None, + client_info=DEFAULT_CLIENT_INFO, + ) + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "GenerativeQuestionServiceAsyncClient": + return self + + async def __aexit__(self, exc_type, exc, tb): + await self.transport.close() + + +DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=package_version.__version__ +) + + +__all__ = ("GenerativeQuestionServiceAsyncClient",) diff --git a/packages/google-cloud-retail/google/cloud/retail_v2/services/generative_question_service/client.py b/packages/google-cloud-retail/google/cloud/retail_v2/services/generative_question_service/client.py new file mode 100644 index 000000000000..49c8eb125faf --- /dev/null +++ b/packages/google-cloud-retail/google/cloud/retail_v2/services/generative_question_service/client.py @@ -0,0 +1,1480 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Callable, + Dict, + Mapping, + MutableMapping, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.cloud.retail_v2 import gapic_version as package_version + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault, None] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object, None] # type: ignore + +from google.cloud.location import locations_pb2 # type: ignore +from google.longrunning import operations_pb2 # type: ignore +from google.protobuf import field_mask_pb2 # type: ignore + +from google.cloud.retail_v2.types import ( + generative_question, + generative_question_service, +) + +from .transports.base import DEFAULT_CLIENT_INFO, GenerativeQuestionServiceTransport +from .transports.grpc import GenerativeQuestionServiceGrpcTransport +from .transports.grpc_asyncio import GenerativeQuestionServiceGrpcAsyncIOTransport +from .transports.rest import GenerativeQuestionServiceRestTransport + + +class GenerativeQuestionServiceClientMeta(type): + """Metaclass for the GenerativeQuestionService client. + + This provides class-level methods for building and retrieving + support objects (e.g. transport) without polluting the client instance + objects. + """ + + _transport_registry = ( + OrderedDict() + ) # type: Dict[str, Type[GenerativeQuestionServiceTransport]] + _transport_registry["grpc"] = GenerativeQuestionServiceGrpcTransport + _transport_registry["grpc_asyncio"] = GenerativeQuestionServiceGrpcAsyncIOTransport + _transport_registry["rest"] = GenerativeQuestionServiceRestTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[GenerativeQuestionServiceTransport]: + """Returns an appropriate transport class. + + Args: + label: The name of the desired transport. If none is + provided, then the first transport in the registry is used. + + Returns: + The transport class to use. + """ + # If a specific transport is requested, return that one. + if label: + return cls._transport_registry[label] + + # No transport is requested; return the default (that is, the first one + # in the dictionary). + return next(iter(cls._transport_registry.values())) + + +class GenerativeQuestionServiceClient(metaclass=GenerativeQuestionServiceClientMeta): + """Service for managing LLM generated questions in search + serving. + """ + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "retail.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "retail.{UNIVERSE_DOMAIN}" + _DEFAULT_UNIVERSE = "googleapis.com" + + @classmethod + def from_service_account_info(cls, info: dict, *args, **kwargs): + """Creates an instance of this client using the provided credentials + info. + + Args: + info (dict): The service account private key info. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + GenerativeQuestionServiceClient: The constructed client. + """ + credentials = service_account.Credentials.from_service_account_info(info) + kwargs["credentials"] = credentials + return cls(*args, **kwargs) + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + GenerativeQuestionServiceClient: The constructed client. + """ + credentials = service_account.Credentials.from_service_account_file(filename) + kwargs["credentials"] = credentials + return cls(*args, **kwargs) + + from_service_account_json = from_service_account_file + + @property + def transport(self) -> GenerativeQuestionServiceTransport: + """Returns the transport used by the client instance. + + Returns: + GenerativeQuestionServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def catalog_path( + project: str, + location: str, + catalog: str, + ) -> str: + """Returns a fully-qualified catalog string.""" + return "projects/{project}/locations/{location}/catalogs/{catalog}".format( + project=project, + location=location, + catalog=catalog, + ) + + @staticmethod + def parse_catalog_path(path: str) -> Dict[str, str]: + """Parses a catalog path into its component segments.""" + m = re.match( + r"^projects/(?P.+?)/locations/(?P.+?)/catalogs/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def common_billing_account_path( + billing_account: str, + ) -> str: + """Returns a fully-qualified billing_account string.""" + return "billingAccounts/{billing_account}".format( + billing_account=billing_account, + ) + + @staticmethod + def parse_common_billing_account_path(path: str) -> Dict[str, str]: + """Parse a billing_account path into its component segments.""" + m = re.match(r"^billingAccounts/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_folder_path( + folder: str, + ) -> str: + """Returns a fully-qualified folder string.""" + return "folders/{folder}".format( + folder=folder, + ) + + @staticmethod + def parse_common_folder_path(path: str) -> Dict[str, str]: + """Parse a folder path into its component segments.""" + m = re.match(r"^folders/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_organization_path( + organization: str, + ) -> str: + """Returns a fully-qualified organization string.""" + return "organizations/{organization}".format( + organization=organization, + ) + + @staticmethod + def parse_common_organization_path(path: str) -> Dict[str, str]: + """Parse a organization path into its component segments.""" + m = re.match(r"^organizations/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_project_path( + project: str, + ) -> str: + """Returns a fully-qualified project string.""" + return "projects/{project}".format( + project=project, + ) + + @staticmethod + def parse_common_project_path(path: str) -> Dict[str, str]: + """Parse a project path into its component segments.""" + m = re.match(r"^projects/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_location_path( + project: str, + location: str, + ) -> str: + """Returns a fully-qualified location string.""" + return "projects/{project}/locations/{location}".format( + project=project, + location=location, + ) + + @staticmethod + def parse_common_location_path(path: str) -> Dict[str, str]: + """Parse a location path into its component segments.""" + m = re.match(r"^projects/(?P.+?)/locations/(?P.+?)$", path) + return m.groupdict() if m else {} + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[client_options_lib.ClientOptions] = None + ): + """Deprecated. Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + + warnings.warn( + "get_mtls_endpoint_and_cert_source is deprecated. Use the api_endpoint property instead.", + DeprecationWarning, + ) + if client_options is None: + client_options = client_options_lib.ClientOptions() + use_client_cert = os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") + use_mtls_endpoint = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_client_cert not in ("true", "false"): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + if use_mtls_endpoint not in ("auto", "never", "always"): + raise MutualTLSChannelError( + "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`" + ) + + # Figure out the client cert source to use. + client_cert_source = None + if use_client_cert == "true": + if client_options.client_cert_source: + client_cert_source = client_options.client_cert_source + elif mtls.has_default_client_cert_source(): + client_cert_source = mtls.default_client_cert_source() + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + elif use_mtls_endpoint == "always" or ( + use_mtls_endpoint == "auto" and client_cert_source + ): + api_endpoint = cls.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = cls.DEFAULT_ENDPOINT + + return api_endpoint, client_cert_source + + @staticmethod + def _read_environment_variables(): + """Returns the environment variables used by the client. + + Returns: + Tuple[bool, str, str]: returns the GOOGLE_API_USE_CLIENT_CERTIFICATE, + GOOGLE_API_USE_MTLS_ENDPOINT, and GOOGLE_CLOUD_UNIVERSE_DOMAIN environment variables. + + Raises: + ValueError: If GOOGLE_API_USE_CLIENT_CERTIFICATE is not + any of ["true", "false"]. + google.auth.exceptions.MutualTLSChannelError: If GOOGLE_API_USE_MTLS_ENDPOINT + is not any of ["auto", "never", "always"]. + """ + use_client_cert = os.getenv( + "GOOGLE_API_USE_CLIENT_CERTIFICATE", "false" + ).lower() + use_mtls_endpoint = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto").lower() + universe_domain_env = os.getenv("GOOGLE_CLOUD_UNIVERSE_DOMAIN") + if use_client_cert not in ("true", "false"): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + if use_mtls_endpoint not in ("auto", "never", "always"): + raise MutualTLSChannelError( + "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`" + ) + return use_client_cert == "true", use_mtls_endpoint, universe_domain_env + + @staticmethod + def _get_client_cert_source(provided_cert_source, use_cert_flag): + """Return the client cert source to be used by the client. + + Args: + provided_cert_source (bytes): The client certificate source provided. + use_cert_flag (bool): A flag indicating whether to use the client certificate. + + Returns: + bytes or None: The client cert source to be used by the client. + """ + client_cert_source = None + if use_cert_flag: + if provided_cert_source: + client_cert_source = provided_cert_source + elif mtls.has_default_client_cert_source(): + client_cert_source = mtls.default_client_cert_source() + return client_cert_source + + @staticmethod + def _get_api_endpoint( + api_override, client_cert_source, universe_domain, use_mtls_endpoint + ): + """Return the API endpoint used by the client. + + Args: + api_override (str): The API endpoint override. If specified, this is always + the return value of this function and the other arguments are not used. + client_cert_source (bytes): The client certificate source used by the client. + universe_domain (str): The universe domain used by the client. + use_mtls_endpoint (str): How to use the mTLS endpoint, which depends also on the other parameters. + Possible values are "always", "auto", or "never". + + Returns: + str: The API endpoint to be used by the client. + """ + if api_override is not None: + api_endpoint = api_override + elif use_mtls_endpoint == "always" or ( + use_mtls_endpoint == "auto" and client_cert_source + ): + _default_universe = GenerativeQuestionServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = GenerativeQuestionServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + GenerativeQuestionServiceClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=universe_domain + ) + ) + return api_endpoint + + @staticmethod + def _get_universe_domain( + client_universe_domain: Optional[str], universe_domain_env: Optional[str] + ) -> str: + """Return the universe domain used by the client. + + Args: + client_universe_domain (Optional[str]): The universe domain configured via the client options. + universe_domain_env (Optional[str]): The universe domain configured via the "GOOGLE_CLOUD_UNIVERSE_DOMAIN" environment variable. + + Returns: + str: The universe domain to be used by the client. + + Raises: + ValueError: If the universe domain is an empty string. + """ + universe_domain = GenerativeQuestionServiceClient._DEFAULT_UNIVERSE + if client_universe_domain is not None: + universe_domain = client_universe_domain + elif universe_domain_env is not None: + universe_domain = universe_domain_env + if len(universe_domain.strip()) == 0: + raise ValueError("Universe Domain cannot be an empty string.") + return universe_domain + + @staticmethod + def _compare_universes( + client_universe: str, credentials: ga_credentials.Credentials + ) -> bool: + """Returns True iff the universe domains used by the client and credentials match. + + Args: + client_universe (str): The universe domain configured via the client options. + credentials (ga_credentials.Credentials): The credentials being used in the client. + + Returns: + bool: True iff client_universe matches the universe in credentials. + + Raises: + ValueError: when client_universe does not match the universe in credentials. + """ + + default_universe = GenerativeQuestionServiceClient._DEFAULT_UNIVERSE + credentials_universe = getattr(credentials, "universe_domain", default_universe) + + if client_universe != credentials_universe: + raise ValueError( + "The configured universe domain " + f"({client_universe}) does not match the universe domain " + f"found in the credentials ({credentials_universe}). " + "If you haven't configured the universe domain explicitly, " + f"`{default_universe}` is the default." + ) + return True + + def _validate_universe_domain(self): + """Validates client's and credentials' universe domains are consistent. + + Returns: + bool: True iff the configured universe domain is valid. + + Raises: + ValueError: If the configured universe domain is not valid. + """ + self._is_universe_domain_valid = ( + self._is_universe_domain_valid + or GenerativeQuestionServiceClient._compare_universes( + self.universe_domain, self.transport._credentials + ) + ) + return self._is_universe_domain_valid + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used by the client instance. + """ + return self._universe_domain + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + GenerativeQuestionServiceTransport, + Callable[..., GenerativeQuestionServiceTransport], + ] + ] = None, + client_options: Optional[Union[client_options_lib.ClientOptions, dict]] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the generative question service client. + + Args: + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + transport (Optional[Union[str,GenerativeQuestionServiceTransport,Callable[..., GenerativeQuestionServiceTransport]]]): + The transport to use, or a Callable that constructs and returns a new transport. + If a Callable is given, it will be called with the same set of initialization + arguments as used in the GenerativeQuestionServiceTransport constructor. + If set to None, a transport is chosen automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): + Custom options for the client. + + 1. The ``api_endpoint`` property can be used to override the + default endpoint provided by the client when ``transport`` is + not explicitly provided. Only if this property is not set and + ``transport`` was not explicitly provided, the endpoint is + determined by the GOOGLE_API_USE_MTLS_ENDPOINT environment + variable, which have one of the following values: + "always" (always use the default mTLS endpoint), "never" (always + use the default regular endpoint) and "auto" (auto-switch to the + default mTLS endpoint if client certificate is present; this is + the default value). + + 2. If the GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide a client certificate for mTLS transport. If + not provided, the default SSL client certificate will be used if + present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not + set, no client certificate will be used. + + 3. The ``universe_domain`` property can be used to override the + default "googleapis.com" universe. Note that the ``api_endpoint`` + property still takes precedence; and ``universe_domain`` is + currently not supported for mTLS. + + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + """ + self._client_options = client_options + if isinstance(self._client_options, dict): + self._client_options = client_options_lib.from_dict(self._client_options) + if self._client_options is None: + self._client_options = client_options_lib.ClientOptions() + self._client_options = cast( + client_options_lib.ClientOptions, self._client_options + ) + + universe_domain_opt = getattr(self._client_options, "universe_domain", None) + + ( + self._use_client_cert, + self._use_mtls_endpoint, + self._universe_domain_env, + ) = GenerativeQuestionServiceClient._read_environment_variables() + self._client_cert_source = ( + GenerativeQuestionServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = GenerativeQuestionServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + api_key_value = getattr(self._client_options, "api_key", None) + if api_key_value and credentials: + raise ValueError( + "client_options.api_key and credentials are mutually exclusive" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + transport_provided = isinstance(transport, GenerativeQuestionServiceTransport) + if transport_provided: + # transport is a GenerativeQuestionServiceTransport instance. + if credentials or self._client_options.credentials_file or api_key_value: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if self._client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = cast(GenerativeQuestionServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or GenerativeQuestionServiceClient._get_api_endpoint( + self._client_options.api_endpoint, + self._client_cert_source, + self._universe_domain, + self._use_mtls_endpoint, + ) + ) + + if not transport_provided: + import google.auth._default # type: ignore + + if api_key_value and hasattr( + google.auth._default, "get_api_key_credentials" + ): + credentials = google.auth._default.get_api_key_credentials( + api_key_value + ) + + transport_init: Union[ + Type[GenerativeQuestionServiceTransport], + Callable[..., GenerativeQuestionServiceTransport], + ] = ( + GenerativeQuestionServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast(Callable[..., GenerativeQuestionServiceTransport], transport) + ) + # initialize with the provided callable or the passed in class + self._transport = transport_init( + credentials=credentials, + credentials_file=self._client_options.credentials_file, + host=self._api_endpoint, + scopes=self._client_options.scopes, + client_cert_source_for_mtls=self._client_cert_source, + quota_project_id=self._client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + api_audience=self._client_options.api_audience, + ) + + def update_generative_questions_feature_config( + self, + request: Optional[ + Union[ + generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest, + dict, + ] + ] = None, + *, + generative_questions_feature_config: Optional[ + generative_question.GenerativeQuestionsFeatureConfig + ] = None, + update_mask: Optional[field_mask_pb2.FieldMask] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> generative_question.GenerativeQuestionsFeatureConfig: + r"""Manages overal generative question feature state -- + enables toggling feature on and off. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import retail_v2 + + def sample_update_generative_questions_feature_config(): + # Create a client + client = retail_v2.GenerativeQuestionServiceClient() + + # Initialize request argument(s) + generative_questions_feature_config = retail_v2.GenerativeQuestionsFeatureConfig() + generative_questions_feature_config.catalog = "catalog_value" + + request = retail_v2.UpdateGenerativeQuestionsFeatureConfigRequest( + generative_questions_feature_config=generative_questions_feature_config, + ) + + # Make the request + response = client.update_generative_questions_feature_config(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.retail_v2.types.UpdateGenerativeQuestionsFeatureConfigRequest, dict]): + The request object. Request for + UpdateGenerativeQuestionsFeatureConfig + method. + generative_questions_feature_config (google.cloud.retail_v2.types.GenerativeQuestionsFeatureConfig): + Required. The configuration managing + the feature state. + + This corresponds to the ``generative_questions_feature_config`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + update_mask (google.protobuf.field_mask_pb2.FieldMask): + Optional. Indicates which fields in the provided + [GenerativeQuestionsFeatureConfig][google.cloud.retail.v2.GenerativeQuestionsFeatureConfig] + to update. If not set or empty, all supported fields are + updated. + + This corresponds to the ``update_mask`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.retail_v2.types.GenerativeQuestionsFeatureConfig: + Configuration for overall generative + question feature state. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([generative_questions_feature_config, update_mask]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance( + request, + generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest, + ): + request = generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if generative_questions_feature_config is not None: + request.generative_questions_feature_config = ( + generative_questions_feature_config + ) + if update_mask is not None: + request.update_mask = update_mask + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.update_generative_questions_feature_config + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + ( + ( + "generative_questions_feature_config.catalog", + request.generative_questions_feature_config.catalog, + ), + ) + ), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + def get_generative_questions_feature_config( + self, + request: Optional[ + Union[ + generative_question_service.GetGenerativeQuestionsFeatureConfigRequest, + dict, + ] + ] = None, + *, + catalog: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> generative_question.GenerativeQuestionsFeatureConfig: + r"""Manages overal generative question feature state -- + enables toggling feature on and off. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import retail_v2 + + def sample_get_generative_questions_feature_config(): + # Create a client + client = retail_v2.GenerativeQuestionServiceClient() + + # Initialize request argument(s) + request = retail_v2.GetGenerativeQuestionsFeatureConfigRequest( + catalog="catalog_value", + ) + + # Make the request + response = client.get_generative_questions_feature_config(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.retail_v2.types.GetGenerativeQuestionsFeatureConfigRequest, dict]): + The request object. Request for + GetGenerativeQuestionsFeatureConfig + method. + catalog (str): + Required. Resource name of the parent + catalog. Format: + projects/{project}/locations/{location}/catalogs/{catalog} + + This corresponds to the ``catalog`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.retail_v2.types.GenerativeQuestionsFeatureConfig: + Configuration for overall generative + question feature state. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([catalog]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance( + request, + generative_question_service.GetGenerativeQuestionsFeatureConfigRequest, + ): + request = ( + generative_question_service.GetGenerativeQuestionsFeatureConfigRequest( + request + ) + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if catalog is not None: + request.catalog = catalog + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.get_generative_questions_feature_config + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("catalog", request.catalog),)), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + def list_generative_question_configs( + self, + request: Optional[ + Union[ + generative_question_service.ListGenerativeQuestionConfigsRequest, dict + ] + ] = None, + *, + parent: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> generative_question_service.ListGenerativeQuestionConfigsResponse: + r"""Returns all questions for a given catalog. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import retail_v2 + + def sample_list_generative_question_configs(): + # Create a client + client = retail_v2.GenerativeQuestionServiceClient() + + # Initialize request argument(s) + request = retail_v2.ListGenerativeQuestionConfigsRequest( + parent="parent_value", + ) + + # Make the request + response = client.list_generative_question_configs(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.retail_v2.types.ListGenerativeQuestionConfigsRequest, dict]): + The request object. Request for ListQuestions method. + parent (str): + Required. Resource name of the parent + catalog. Format: + projects/{project}/locations/{location}/catalogs/{catalog} + + This corresponds to the ``parent`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.retail_v2.types.ListGenerativeQuestionConfigsResponse: + Response for ListQuestions method. + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([parent]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance( + request, generative_question_service.ListGenerativeQuestionConfigsRequest + ): + request = generative_question_service.ListGenerativeQuestionConfigsRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if parent is not None: + request.parent = parent + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.list_generative_question_configs + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + def update_generative_question_config( + self, + request: Optional[ + Union[ + generative_question_service.UpdateGenerativeQuestionConfigRequest, dict + ] + ] = None, + *, + generative_question_config: Optional[ + generative_question.GenerativeQuestionConfig + ] = None, + update_mask: Optional[field_mask_pb2.FieldMask] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> generative_question.GenerativeQuestionConfig: + r"""Allows management of individual questions. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import retail_v2 + + def sample_update_generative_question_config(): + # Create a client + client = retail_v2.GenerativeQuestionServiceClient() + + # Initialize request argument(s) + generative_question_config = retail_v2.GenerativeQuestionConfig() + generative_question_config.catalog = "catalog_value" + generative_question_config.facet = "facet_value" + + request = retail_v2.UpdateGenerativeQuestionConfigRequest( + generative_question_config=generative_question_config, + ) + + # Make the request + response = client.update_generative_question_config(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.retail_v2.types.UpdateGenerativeQuestionConfigRequest, dict]): + The request object. Request for + UpdateGenerativeQuestionConfig method. + generative_question_config (google.cloud.retail_v2.types.GenerativeQuestionConfig): + Required. The question to update. + This corresponds to the ``generative_question_config`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + update_mask (google.protobuf.field_mask_pb2.FieldMask): + Optional. Indicates which fields in the provided + [GenerativeQuestionConfig][google.cloud.retail.v2.GenerativeQuestionConfig] + to update. The following are NOT supported: + + - [GenerativeQuestionConfig.frequency][google.cloud.retail.v2.GenerativeQuestionConfig.frequency] + + If not set or empty, all supported fields are updated. + + This corresponds to the ``update_mask`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.retail_v2.types.GenerativeQuestionConfig: + Configuration for a single generated + question. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([generative_question_config, update_mask]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance( + request, generative_question_service.UpdateGenerativeQuestionConfigRequest + ): + request = generative_question_service.UpdateGenerativeQuestionConfigRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if generative_question_config is not None: + request.generative_question_config = generative_question_config + if update_mask is not None: + request.update_mask = update_mask + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.update_generative_question_config + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + ( + ( + "generative_question_config.catalog", + request.generative_question_config.catalog, + ), + ) + ), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + def batch_update_generative_question_configs( + self, + request: Optional[ + Union[ + generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest, + dict, + ] + ] = None, + *, + parent: Optional[str] = None, + requests: Optional[ + MutableSequence[ + generative_question_service.UpdateGenerativeQuestionConfigRequest + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse: + r"""Allows management of multiple questions. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import retail_v2 + + def sample_batch_update_generative_question_configs(): + # Create a client + client = retail_v2.GenerativeQuestionServiceClient() + + # Initialize request argument(s) + requests = retail_v2.UpdateGenerativeQuestionConfigRequest() + requests.generative_question_config.catalog = "catalog_value" + requests.generative_question_config.facet = "facet_value" + + request = retail_v2.BatchUpdateGenerativeQuestionConfigsRequest( + requests=requests, + ) + + # Make the request + response = client.batch_update_generative_question_configs(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.retail_v2.types.BatchUpdateGenerativeQuestionConfigsRequest, dict]): + The request object. Request for + BatchUpdateGenerativeQuestionConfig + method. + parent (str): + Optional. Resource name of the parent + catalog. Format: + projects/{project}/locations/{location}/catalogs/{catalog} + + This corresponds to the ``parent`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + requests (MutableSequence[google.cloud.retail_v2.types.UpdateGenerativeQuestionConfigRequest]): + Required. The updates question + configs. + + This corresponds to the ``requests`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.retail_v2.types.BatchUpdateGenerativeQuestionConfigsResponse: + Aggregated response for + UpdateGenerativeQuestionConfig method. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([parent, requests]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance( + request, + generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest, + ): + request = ( + generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest( + request + ) + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if parent is not None: + request.parent = parent + if requests is not None: + request.requests = requests + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.batch_update_generative_question_configs + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + def __enter__(self) -> "GenerativeQuestionServiceClient": + return self + + def __exit__(self, type, value, traceback): + """Releases underlying transport's resources. + + .. warning:: + ONLY use as a context manager if the transport is NOT shared + with other clients! Exiting the with block will CLOSE the transport + and may cause errors in other clients! + """ + self.transport.close() + + def list_operations( + self, + request: Optional[operations_pb2.ListOperationsRequest] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operations_pb2.ListOperationsResponse: + r"""Lists operations that match the specified filter in the request. + + Args: + request (:class:`~.operations_pb2.ListOperationsRequest`): + The request object. Request message for + `ListOperations` method. + retry (google.api_core.retry.Retry): Designation of what errors, + if any, should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + Returns: + ~.operations_pb2.ListOperationsResponse: + Response message for ``ListOperations`` method. + """ + # Create or coerce a protobuf request object. + # The request isn't a proto-plus wrapped type, + # so it must be constructed via keyword expansion. + if isinstance(request, dict): + request = operations_pb2.ListOperationsRequest(**request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method.wrap_method( + self._transport.list_operations, + default_timeout=None, + client_info=DEFAULT_CLIENT_INFO, + ) + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + def get_operation( + self, + request: Optional[operations_pb2.GetOperationRequest] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operations_pb2.Operation: + r"""Gets the latest state of a long-running operation. + + Args: + request (:class:`~.operations_pb2.GetOperationRequest`): + The request object. Request message for + `GetOperation` method. + retry (google.api_core.retry.Retry): Designation of what errors, + if any, should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + Returns: + ~.operations_pb2.Operation: + An ``Operation`` object. + """ + # Create or coerce a protobuf request object. + # The request isn't a proto-plus wrapped type, + # so it must be constructed via keyword expansion. + if isinstance(request, dict): + request = operations_pb2.GetOperationRequest(**request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method.wrap_method( + self._transport.get_operation, + default_timeout=None, + client_info=DEFAULT_CLIENT_INFO, + ) + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=package_version.__version__ +) + + +__all__ = ("GenerativeQuestionServiceClient",) diff --git a/packages/google-cloud-retail/google/cloud/retail_v2/services/generative_question_service/transports/__init__.py b/packages/google-cloud-retail/google/cloud/retail_v2/services/generative_question_service/transports/__init__.py new file mode 100644 index 000000000000..9e57f7d430ba --- /dev/null +++ b/packages/google-cloud-retail/google/cloud/retail_v2/services/generative_question_service/transports/__init__.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +from typing import Dict, Type + +from .base import GenerativeQuestionServiceTransport +from .grpc import GenerativeQuestionServiceGrpcTransport +from .grpc_asyncio import GenerativeQuestionServiceGrpcAsyncIOTransport +from .rest import ( + GenerativeQuestionServiceRestInterceptor, + GenerativeQuestionServiceRestTransport, +) + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[GenerativeQuestionServiceTransport]] +_transport_registry["grpc"] = GenerativeQuestionServiceGrpcTransport +_transport_registry["grpc_asyncio"] = GenerativeQuestionServiceGrpcAsyncIOTransport +_transport_registry["rest"] = GenerativeQuestionServiceRestTransport + +__all__ = ( + "GenerativeQuestionServiceTransport", + "GenerativeQuestionServiceGrpcTransport", + "GenerativeQuestionServiceGrpcAsyncIOTransport", + "GenerativeQuestionServiceRestTransport", + "GenerativeQuestionServiceRestInterceptor", +) diff --git a/packages/google-cloud-retail/google/cloud/retail_v2/services/generative_question_service/transports/base.py b/packages/google-cloud-retail/google/cloud/retail_v2/services/generative_question_service/transports/base.py new file mode 100644 index 000000000000..71e37adc0e19 --- /dev/null +++ b/packages/google-cloud-retail/google/cloud/retail_v2/services/generative_question_service/transports/base.py @@ -0,0 +1,262 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import abc +from typing import Awaitable, Callable, Dict, Optional, Sequence, Union + +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.cloud.location import locations_pb2 # type: ignore +from google.longrunning import operations_pb2 # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.cloud.retail_v2 import gapic_version as package_version +from google.cloud.retail_v2.types import ( + generative_question, + generative_question_service, +) + +DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=package_version.__version__ +) + + +class GenerativeQuestionServiceTransport(abc.ABC): + """Abstract transport class for GenerativeQuestionService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/cloud-platform",) + + DEFAULT_HOST: str = "retail.googleapis.com" + + def __init__( + self, + *, + host: str = DEFAULT_HOST, + credentials: Optional[ga_credentials.Credentials] = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + quota_project_id: Optional[str] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, + api_audience: Optional[str] = None, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to (default: 'retail.googleapis.com'). + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, **scopes_kwargs, quota_project_id=quota_project_id + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr(service_account.Credentials, "with_always_use_jwt_access") + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.update_generative_questions_feature_config: gapic_v1.method.wrap_method( + self.update_generative_questions_feature_config, + default_timeout=None, + client_info=client_info, + ), + self.get_generative_questions_feature_config: gapic_v1.method.wrap_method( + self.get_generative_questions_feature_config, + default_timeout=None, + client_info=client_info, + ), + self.list_generative_question_configs: gapic_v1.method.wrap_method( + self.list_generative_question_configs, + default_timeout=None, + client_info=client_info, + ), + self.update_generative_question_config: gapic_v1.method.wrap_method( + self.update_generative_question_config, + default_timeout=None, + client_info=client_info, + ), + self.batch_update_generative_question_configs: gapic_v1.method.wrap_method( + self.batch_update_generative_question_configs, + default_timeout=None, + client_info=client_info, + ), + } + + def close(self): + """Closes resources associated with the transport. + + .. warning:: + Only call this method if the transport is NOT shared + with other clients - this may cause errors in other clients! + """ + raise NotImplementedError() + + @property + def update_generative_questions_feature_config( + self, + ) -> Callable[ + [generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest], + Union[ + generative_question.GenerativeQuestionsFeatureConfig, + Awaitable[generative_question.GenerativeQuestionsFeatureConfig], + ], + ]: + raise NotImplementedError() + + @property + def get_generative_questions_feature_config( + self, + ) -> Callable[ + [generative_question_service.GetGenerativeQuestionsFeatureConfigRequest], + Union[ + generative_question.GenerativeQuestionsFeatureConfig, + Awaitable[generative_question.GenerativeQuestionsFeatureConfig], + ], + ]: + raise NotImplementedError() + + @property + def list_generative_question_configs( + self, + ) -> Callable[ + [generative_question_service.ListGenerativeQuestionConfigsRequest], + Union[ + generative_question_service.ListGenerativeQuestionConfigsResponse, + Awaitable[ + generative_question_service.ListGenerativeQuestionConfigsResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def update_generative_question_config( + self, + ) -> Callable[ + [generative_question_service.UpdateGenerativeQuestionConfigRequest], + Union[ + generative_question.GenerativeQuestionConfig, + Awaitable[generative_question.GenerativeQuestionConfig], + ], + ]: + raise NotImplementedError() + + @property + def batch_update_generative_question_configs( + self, + ) -> Callable[ + [generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest], + Union[ + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse, + Awaitable[ + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def list_operations( + self, + ) -> Callable[ + [operations_pb2.ListOperationsRequest], + Union[ + operations_pb2.ListOperationsResponse, + Awaitable[operations_pb2.ListOperationsResponse], + ], + ]: + raise NotImplementedError() + + @property + def get_operation( + self, + ) -> Callable[ + [operations_pb2.GetOperationRequest], + Union[operations_pb2.Operation, Awaitable[operations_pb2.Operation]], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("GenerativeQuestionServiceTransport",) diff --git a/packages/google-cloud-retail/google/cloud/retail_v2/services/generative_question_service/transports/grpc.py b/packages/google-cloud-retail/google/cloud/retail_v2/services/generative_question_service/transports/grpc.py new file mode 100644 index 000000000000..5e76434ca7e2 --- /dev/null +++ b/packages/google-cloud-retail/google/cloud/retail_v2/services/generative_question_service/transports/grpc.py @@ -0,0 +1,449 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from typing import Callable, Dict, Optional, Sequence, Tuple, Union +import warnings + +from google.api_core import gapic_v1, grpc_helpers +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.cloud.location import locations_pb2 # type: ignore +from google.longrunning import operations_pb2 # type: ignore +import grpc # type: ignore + +from google.cloud.retail_v2.types import ( + generative_question, + generative_question_service, +) + +from .base import DEFAULT_CLIENT_INFO, GenerativeQuestionServiceTransport + + +class GenerativeQuestionServiceGrpcTransport(GenerativeQuestionServiceTransport): + """gRPC backend transport for GenerativeQuestionService. + + Service for managing LLM generated questions in search + serving. + + This class defines the same methods as the primary client, so the + primary client can load the underlying transport implementation + and call it. + + It sends protocol buffers over the wire using gRPC (which is built on + top of HTTP/2); the ``grpcio`` package must be installed. + """ + + _stubs: Dict[str, Callable] + + def __init__( + self, + *, + host: str = "retail.googleapis.com", + credentials: Optional[ga_credentials.Credentials] = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + channel: Optional[Union[grpc.Channel, Callable[..., grpc.Channel]]] = None, + api_mtls_endpoint: Optional[str] = None, + client_cert_source: Optional[Callable[[], Tuple[bytes, bytes]]] = None, + ssl_channel_credentials: Optional[grpc.ChannelCredentials] = None, + client_cert_source_for_mtls: Optional[Callable[[], Tuple[bytes, bytes]]] = None, + quota_project_id: Optional[str] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, + api_audience: Optional[str] = None, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to (default: 'retail.googleapis.com'). + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if a ``channel`` instance is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if a ``channel`` instance is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if a ``channel`` instance is provided. + channel (Optional[Union[grpc.Channel, Callable[..., grpc.Channel]]]): + A ``Channel`` instance through which to make calls, or a Callable + that constructs and returns one. If set to None, ``self.create_channel`` + is used to create the channel. If a Callable is given, it will be called + with the same arguments as used in ``self.create_channel``. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if a ``channel`` instance is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if a ``channel`` instance or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn("client_cert_source is deprecated", DeprecationWarning) + + if isinstance(channel, grpc.Channel): + # Ignore credentials if a channel was passed. + credentials = None + self._ignore_credentials = True + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + else: + self._ssl_channel_credentials = SslCredentials().ssl_credentials + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + api_audience=api_audience, + ) + + if not self._grpc_channel: + # initialize with the provided callable or the default channel + channel_init = channel or type(self).create_channel + self._grpc_channel = channel_init( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "retail.googleapis.com", + credentials: Optional[ga_credentials.Credentials] = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + quota_project_id: Optional[str] = None, + **kwargs, + ) -> grpc.Channel: + """Create and return a gRPC channel object. + Args: + host (Optional[str]): The host for the channel to use. + credentials (Optional[~.Credentials]): The + authorization credentials to attach to requests. These + credentials identify this application to the service. If + none are specified, the client will attempt to ascertain + the credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def update_generative_questions_feature_config( + self, + ) -> Callable[ + [generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest], + generative_question.GenerativeQuestionsFeatureConfig, + ]: + r"""Return a callable for the update generative questions + feature config method over gRPC. + + Manages overal generative question feature state -- + enables toggling feature on and off. + + Returns: + Callable[[~.UpdateGenerativeQuestionsFeatureConfigRequest], + ~.GenerativeQuestionsFeatureConfig]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "update_generative_questions_feature_config" not in self._stubs: + self._stubs[ + "update_generative_questions_feature_config" + ] = self.grpc_channel.unary_unary( + "/google.cloud.retail.v2.GenerativeQuestionService/UpdateGenerativeQuestionsFeatureConfig", + request_serializer=generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest.serialize, + response_deserializer=generative_question.GenerativeQuestionsFeatureConfig.deserialize, + ) + return self._stubs["update_generative_questions_feature_config"] + + @property + def get_generative_questions_feature_config( + self, + ) -> Callable[ + [generative_question_service.GetGenerativeQuestionsFeatureConfigRequest], + generative_question.GenerativeQuestionsFeatureConfig, + ]: + r"""Return a callable for the get generative questions + feature config method over gRPC. + + Manages overal generative question feature state -- + enables toggling feature on and off. + + Returns: + Callable[[~.GetGenerativeQuestionsFeatureConfigRequest], + ~.GenerativeQuestionsFeatureConfig]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "get_generative_questions_feature_config" not in self._stubs: + self._stubs[ + "get_generative_questions_feature_config" + ] = self.grpc_channel.unary_unary( + "/google.cloud.retail.v2.GenerativeQuestionService/GetGenerativeQuestionsFeatureConfig", + request_serializer=generative_question_service.GetGenerativeQuestionsFeatureConfigRequest.serialize, + response_deserializer=generative_question.GenerativeQuestionsFeatureConfig.deserialize, + ) + return self._stubs["get_generative_questions_feature_config"] + + @property + def list_generative_question_configs( + self, + ) -> Callable[ + [generative_question_service.ListGenerativeQuestionConfigsRequest], + generative_question_service.ListGenerativeQuestionConfigsResponse, + ]: + r"""Return a callable for the list generative question + configs method over gRPC. + + Returns all questions for a given catalog. + + Returns: + Callable[[~.ListGenerativeQuestionConfigsRequest], + ~.ListGenerativeQuestionConfigsResponse]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "list_generative_question_configs" not in self._stubs: + self._stubs[ + "list_generative_question_configs" + ] = self.grpc_channel.unary_unary( + "/google.cloud.retail.v2.GenerativeQuestionService/ListGenerativeQuestionConfigs", + request_serializer=generative_question_service.ListGenerativeQuestionConfigsRequest.serialize, + response_deserializer=generative_question_service.ListGenerativeQuestionConfigsResponse.deserialize, + ) + return self._stubs["list_generative_question_configs"] + + @property + def update_generative_question_config( + self, + ) -> Callable[ + [generative_question_service.UpdateGenerativeQuestionConfigRequest], + generative_question.GenerativeQuestionConfig, + ]: + r"""Return a callable for the update generative question + config method over gRPC. + + Allows management of individual questions. + + Returns: + Callable[[~.UpdateGenerativeQuestionConfigRequest], + ~.GenerativeQuestionConfig]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "update_generative_question_config" not in self._stubs: + self._stubs[ + "update_generative_question_config" + ] = self.grpc_channel.unary_unary( + "/google.cloud.retail.v2.GenerativeQuestionService/UpdateGenerativeQuestionConfig", + request_serializer=generative_question_service.UpdateGenerativeQuestionConfigRequest.serialize, + response_deserializer=generative_question.GenerativeQuestionConfig.deserialize, + ) + return self._stubs["update_generative_question_config"] + + @property + def batch_update_generative_question_configs( + self, + ) -> Callable[ + [generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest], + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse, + ]: + r"""Return a callable for the batch update generative + question configs method over gRPC. + + Allows management of multiple questions. + + Returns: + Callable[[~.BatchUpdateGenerativeQuestionConfigsRequest], + ~.BatchUpdateGenerativeQuestionConfigsResponse]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "batch_update_generative_question_configs" not in self._stubs: + self._stubs[ + "batch_update_generative_question_configs" + ] = self.grpc_channel.unary_unary( + "/google.cloud.retail.v2.GenerativeQuestionService/BatchUpdateGenerativeQuestionConfigs", + request_serializer=generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest.serialize, + response_deserializer=generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse.deserialize, + ) + return self._stubs["batch_update_generative_question_configs"] + + def close(self): + self.grpc_channel.close() + + @property + def get_operation( + self, + ) -> Callable[[operations_pb2.GetOperationRequest], operations_pb2.Operation]: + r"""Return a callable for the get_operation method over gRPC.""" + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "get_operation" not in self._stubs: + self._stubs["get_operation"] = self.grpc_channel.unary_unary( + "/google.longrunning.Operations/GetOperation", + request_serializer=operations_pb2.GetOperationRequest.SerializeToString, + response_deserializer=operations_pb2.Operation.FromString, + ) + return self._stubs["get_operation"] + + @property + def list_operations( + self, + ) -> Callable[ + [operations_pb2.ListOperationsRequest], operations_pb2.ListOperationsResponse + ]: + r"""Return a callable for the list_operations method over gRPC.""" + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "list_operations" not in self._stubs: + self._stubs["list_operations"] = self.grpc_channel.unary_unary( + "/google.longrunning.Operations/ListOperations", + request_serializer=operations_pb2.ListOperationsRequest.SerializeToString, + response_deserializer=operations_pb2.ListOperationsResponse.FromString, + ) + return self._stubs["list_operations"] + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("GenerativeQuestionServiceGrpcTransport",) diff --git a/packages/google-cloud-retail/google/cloud/retail_v2/services/generative_question_service/transports/grpc_asyncio.py b/packages/google-cloud-retail/google/cloud/retail_v2/services/generative_question_service/transports/grpc_asyncio.py new file mode 100644 index 000000000000..513bec5b30b3 --- /dev/null +++ b/packages/google-cloud-retail/google/cloud/retail_v2/services/generative_question_service/transports/grpc_asyncio.py @@ -0,0 +1,481 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union +import warnings + +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1, grpc_helpers_async +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.cloud.location import locations_pb2 # type: ignore +from google.longrunning import operations_pb2 # type: ignore +import grpc # type: ignore +from grpc.experimental import aio # type: ignore + +from google.cloud.retail_v2.types import ( + generative_question, + generative_question_service, +) + +from .base import DEFAULT_CLIENT_INFO, GenerativeQuestionServiceTransport +from .grpc import GenerativeQuestionServiceGrpcTransport + + +class GenerativeQuestionServiceGrpcAsyncIOTransport(GenerativeQuestionServiceTransport): + """gRPC AsyncIO backend transport for GenerativeQuestionService. + + Service for managing LLM generated questions in search + serving. + + This class defines the same methods as the primary client, so the + primary client can load the underlying transport implementation + and call it. + + It sends protocol buffers over the wire using gRPC (which is built on + top of HTTP/2); the ``grpcio`` package must be installed. + """ + + _grpc_channel: aio.Channel + _stubs: Dict[str, Callable] = {} + + @classmethod + def create_channel( + cls, + host: str = "retail.googleapis.com", + credentials: Optional[ga_credentials.Credentials] = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + quota_project_id: Optional[str] = None, + **kwargs, + ) -> aio.Channel: + """Create and return a gRPC AsyncIO channel object. + Args: + host (Optional[str]): The host for the channel to use. + credentials (Optional[~.Credentials]): The + authorization credentials to attach to requests. These + credentials identify this application to the service. If + none are specified, the client will attempt to ascertain + the credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + aio.Channel: A gRPC AsyncIO channel object. + """ + + return grpc_helpers_async.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + def __init__( + self, + *, + host: str = "retail.googleapis.com", + credentials: Optional[ga_credentials.Credentials] = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + channel: Optional[Union[aio.Channel, Callable[..., aio.Channel]]] = None, + api_mtls_endpoint: Optional[str] = None, + client_cert_source: Optional[Callable[[], Tuple[bytes, bytes]]] = None, + ssl_channel_credentials: Optional[grpc.ChannelCredentials] = None, + client_cert_source_for_mtls: Optional[Callable[[], Tuple[bytes, bytes]]] = None, + quota_project_id: Optional[str] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, + api_audience: Optional[str] = None, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to (default: 'retail.googleapis.com'). + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if a ``channel`` instance is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if a ``channel`` instance is provided. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + channel (Optional[Union[aio.Channel, Callable[..., aio.Channel]]]): + A ``Channel`` instance through which to make calls, or a Callable + that constructs and returns one. If set to None, ``self.create_channel`` + is used to create the channel. If a Callable is given, it will be called + with the same arguments as used in ``self.create_channel``. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if a ``channel`` instance is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if a ``channel`` instance or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn("client_cert_source is deprecated", DeprecationWarning) + + if isinstance(channel, aio.Channel): + # Ignore credentials if a channel was passed. + credentials = None + self._ignore_credentials = True + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + else: + self._ssl_channel_credentials = SslCredentials().ssl_credentials + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + api_audience=api_audience, + ) + + if not self._grpc_channel: + # initialize with the provided callable or the default channel + channel_init = channel or type(self).create_channel + self._grpc_channel = channel_init( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @property + def grpc_channel(self) -> aio.Channel: + """Create the channel designed to connect to this service. + + This property caches on the instance; repeated calls return + the same channel. + """ + # Return the channel from cache. + return self._grpc_channel + + @property + def update_generative_questions_feature_config( + self, + ) -> Callable[ + [generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest], + Awaitable[generative_question.GenerativeQuestionsFeatureConfig], + ]: + r"""Return a callable for the update generative questions + feature config method over gRPC. + + Manages overal generative question feature state -- + enables toggling feature on and off. + + Returns: + Callable[[~.UpdateGenerativeQuestionsFeatureConfigRequest], + Awaitable[~.GenerativeQuestionsFeatureConfig]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "update_generative_questions_feature_config" not in self._stubs: + self._stubs[ + "update_generative_questions_feature_config" + ] = self.grpc_channel.unary_unary( + "/google.cloud.retail.v2.GenerativeQuestionService/UpdateGenerativeQuestionsFeatureConfig", + request_serializer=generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest.serialize, + response_deserializer=generative_question.GenerativeQuestionsFeatureConfig.deserialize, + ) + return self._stubs["update_generative_questions_feature_config"] + + @property + def get_generative_questions_feature_config( + self, + ) -> Callable[ + [generative_question_service.GetGenerativeQuestionsFeatureConfigRequest], + Awaitable[generative_question.GenerativeQuestionsFeatureConfig], + ]: + r"""Return a callable for the get generative questions + feature config method over gRPC. + + Manages overal generative question feature state -- + enables toggling feature on and off. + + Returns: + Callable[[~.GetGenerativeQuestionsFeatureConfigRequest], + Awaitable[~.GenerativeQuestionsFeatureConfig]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "get_generative_questions_feature_config" not in self._stubs: + self._stubs[ + "get_generative_questions_feature_config" + ] = self.grpc_channel.unary_unary( + "/google.cloud.retail.v2.GenerativeQuestionService/GetGenerativeQuestionsFeatureConfig", + request_serializer=generative_question_service.GetGenerativeQuestionsFeatureConfigRequest.serialize, + response_deserializer=generative_question.GenerativeQuestionsFeatureConfig.deserialize, + ) + return self._stubs["get_generative_questions_feature_config"] + + @property + def list_generative_question_configs( + self, + ) -> Callable[ + [generative_question_service.ListGenerativeQuestionConfigsRequest], + Awaitable[generative_question_service.ListGenerativeQuestionConfigsResponse], + ]: + r"""Return a callable for the list generative question + configs method over gRPC. + + Returns all questions for a given catalog. + + Returns: + Callable[[~.ListGenerativeQuestionConfigsRequest], + Awaitable[~.ListGenerativeQuestionConfigsResponse]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "list_generative_question_configs" not in self._stubs: + self._stubs[ + "list_generative_question_configs" + ] = self.grpc_channel.unary_unary( + "/google.cloud.retail.v2.GenerativeQuestionService/ListGenerativeQuestionConfigs", + request_serializer=generative_question_service.ListGenerativeQuestionConfigsRequest.serialize, + response_deserializer=generative_question_service.ListGenerativeQuestionConfigsResponse.deserialize, + ) + return self._stubs["list_generative_question_configs"] + + @property + def update_generative_question_config( + self, + ) -> Callable[ + [generative_question_service.UpdateGenerativeQuestionConfigRequest], + Awaitable[generative_question.GenerativeQuestionConfig], + ]: + r"""Return a callable for the update generative question + config method over gRPC. + + Allows management of individual questions. + + Returns: + Callable[[~.UpdateGenerativeQuestionConfigRequest], + Awaitable[~.GenerativeQuestionConfig]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "update_generative_question_config" not in self._stubs: + self._stubs[ + "update_generative_question_config" + ] = self.grpc_channel.unary_unary( + "/google.cloud.retail.v2.GenerativeQuestionService/UpdateGenerativeQuestionConfig", + request_serializer=generative_question_service.UpdateGenerativeQuestionConfigRequest.serialize, + response_deserializer=generative_question.GenerativeQuestionConfig.deserialize, + ) + return self._stubs["update_generative_question_config"] + + @property + def batch_update_generative_question_configs( + self, + ) -> Callable[ + [generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest], + Awaitable[ + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse + ], + ]: + r"""Return a callable for the batch update generative + question configs method over gRPC. + + Allows management of multiple questions. + + Returns: + Callable[[~.BatchUpdateGenerativeQuestionConfigsRequest], + Awaitable[~.BatchUpdateGenerativeQuestionConfigsResponse]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "batch_update_generative_question_configs" not in self._stubs: + self._stubs[ + "batch_update_generative_question_configs" + ] = self.grpc_channel.unary_unary( + "/google.cloud.retail.v2.GenerativeQuestionService/BatchUpdateGenerativeQuestionConfigs", + request_serializer=generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest.serialize, + response_deserializer=generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse.deserialize, + ) + return self._stubs["batch_update_generative_question_configs"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.update_generative_questions_feature_config: gapic_v1.method_async.wrap_method( + self.update_generative_questions_feature_config, + default_timeout=None, + client_info=client_info, + ), + self.get_generative_questions_feature_config: gapic_v1.method_async.wrap_method( + self.get_generative_questions_feature_config, + default_timeout=None, + client_info=client_info, + ), + self.list_generative_question_configs: gapic_v1.method_async.wrap_method( + self.list_generative_question_configs, + default_timeout=None, + client_info=client_info, + ), + self.update_generative_question_config: gapic_v1.method_async.wrap_method( + self.update_generative_question_config, + default_timeout=None, + client_info=client_info, + ), + self.batch_update_generative_question_configs: gapic_v1.method_async.wrap_method( + self.batch_update_generative_question_configs, + default_timeout=None, + client_info=client_info, + ), + } + + def close(self): + return self.grpc_channel.close() + + @property + def get_operation( + self, + ) -> Callable[[operations_pb2.GetOperationRequest], operations_pb2.Operation]: + r"""Return a callable for the get_operation method over gRPC.""" + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "get_operation" not in self._stubs: + self._stubs["get_operation"] = self.grpc_channel.unary_unary( + "/google.longrunning.Operations/GetOperation", + request_serializer=operations_pb2.GetOperationRequest.SerializeToString, + response_deserializer=operations_pb2.Operation.FromString, + ) + return self._stubs["get_operation"] + + @property + def list_operations( + self, + ) -> Callable[ + [operations_pb2.ListOperationsRequest], operations_pb2.ListOperationsResponse + ]: + r"""Return a callable for the list_operations method over gRPC.""" + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "list_operations" not in self._stubs: + self._stubs["list_operations"] = self.grpc_channel.unary_unary( + "/google.longrunning.Operations/ListOperations", + request_serializer=operations_pb2.ListOperationsRequest.SerializeToString, + response_deserializer=operations_pb2.ListOperationsResponse.FromString, + ) + return self._stubs["list_operations"] + + +__all__ = ("GenerativeQuestionServiceGrpcAsyncIOTransport",) diff --git a/packages/google-cloud-retail/google/cloud/retail_v2/services/generative_question_service/transports/rest.py b/packages/google-cloud-retail/google/cloud/retail_v2/services/generative_question_service/transports/rest.py new file mode 100644 index 000000000000..cd9fc666b44a --- /dev/null +++ b/packages/google-cloud-retail/google/cloud/retail_v2/services/generative_question_service/transports/rest.py @@ -0,0 +1,1118 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +import dataclasses +import json # type: ignore +import re +from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple, Union +import warnings + +from google.api_core import gapic_v1, path_template, rest_helpers, rest_streaming +from google.api_core import exceptions as core_exceptions +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.transport.requests import AuthorizedSession # type: ignore +from google.cloud.location import locations_pb2 # type: ignore +from google.protobuf import json_format +import grpc # type: ignore +from requests import __version__ as requests_version + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault, None] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object, None] # type: ignore + + +from google.longrunning import operations_pb2 # type: ignore + +from google.cloud.retail_v2.types import ( + generative_question, + generative_question_service, +) + +from .base import DEFAULT_CLIENT_INFO as BASE_DEFAULT_CLIENT_INFO +from .base import GenerativeQuestionServiceTransport + +DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=BASE_DEFAULT_CLIENT_INFO.gapic_version, + grpc_version=None, + rest_version=requests_version, +) + + +class GenerativeQuestionServiceRestInterceptor: + """Interceptor for GenerativeQuestionService. + + Interceptors are used to manipulate requests, request metadata, and responses + in arbitrary ways. + Example use cases include: + * Logging + * Verifying requests according to service or custom semantics + * Stripping extraneous information from responses + + These use cases and more can be enabled by injecting an + instance of a custom subclass when constructing the GenerativeQuestionServiceRestTransport. + + .. code-block:: python + class MyCustomGenerativeQuestionServiceInterceptor(GenerativeQuestionServiceRestInterceptor): + def pre_batch_update_generative_question_configs(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_batch_update_generative_question_configs(self, response): + logging.log(f"Received response: {response}") + return response + + def pre_get_generative_questions_feature_config(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_get_generative_questions_feature_config(self, response): + logging.log(f"Received response: {response}") + return response + + def pre_list_generative_question_configs(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_list_generative_question_configs(self, response): + logging.log(f"Received response: {response}") + return response + + def pre_update_generative_question_config(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_update_generative_question_config(self, response): + logging.log(f"Received response: {response}") + return response + + def pre_update_generative_questions_feature_config(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_update_generative_questions_feature_config(self, response): + logging.log(f"Received response: {response}") + return response + + transport = GenerativeQuestionServiceRestTransport(interceptor=MyCustomGenerativeQuestionServiceInterceptor()) + client = GenerativeQuestionServiceClient(transport=transport) + + + """ + + def pre_batch_update_generative_question_configs( + self, + request: generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[ + generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest, + Sequence[Tuple[str, str]], + ]: + """Pre-rpc interceptor for batch_update_generative_question_configs + + Override in a subclass to manipulate the request or metadata + before they are sent to the GenerativeQuestionService server. + """ + return request, metadata + + def post_batch_update_generative_question_configs( + self, + response: generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse, + ) -> generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse: + """Post-rpc interceptor for batch_update_generative_question_configs + + Override in a subclass to manipulate the response + after it is returned by the GenerativeQuestionService server but before + it is returned to user code. + """ + return response + + def pre_get_generative_questions_feature_config( + self, + request: generative_question_service.GetGenerativeQuestionsFeatureConfigRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[ + generative_question_service.GetGenerativeQuestionsFeatureConfigRequest, + Sequence[Tuple[str, str]], + ]: + """Pre-rpc interceptor for get_generative_questions_feature_config + + Override in a subclass to manipulate the request or metadata + before they are sent to the GenerativeQuestionService server. + """ + return request, metadata + + def post_get_generative_questions_feature_config( + self, response: generative_question.GenerativeQuestionsFeatureConfig + ) -> generative_question.GenerativeQuestionsFeatureConfig: + """Post-rpc interceptor for get_generative_questions_feature_config + + Override in a subclass to manipulate the response + after it is returned by the GenerativeQuestionService server but before + it is returned to user code. + """ + return response + + def pre_list_generative_question_configs( + self, + request: generative_question_service.ListGenerativeQuestionConfigsRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[ + generative_question_service.ListGenerativeQuestionConfigsRequest, + Sequence[Tuple[str, str]], + ]: + """Pre-rpc interceptor for list_generative_question_configs + + Override in a subclass to manipulate the request or metadata + before they are sent to the GenerativeQuestionService server. + """ + return request, metadata + + def post_list_generative_question_configs( + self, + response: generative_question_service.ListGenerativeQuestionConfigsResponse, + ) -> generative_question_service.ListGenerativeQuestionConfigsResponse: + """Post-rpc interceptor for list_generative_question_configs + + Override in a subclass to manipulate the response + after it is returned by the GenerativeQuestionService server but before + it is returned to user code. + """ + return response + + def pre_update_generative_question_config( + self, + request: generative_question_service.UpdateGenerativeQuestionConfigRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[ + generative_question_service.UpdateGenerativeQuestionConfigRequest, + Sequence[Tuple[str, str]], + ]: + """Pre-rpc interceptor for update_generative_question_config + + Override in a subclass to manipulate the request or metadata + before they are sent to the GenerativeQuestionService server. + """ + return request, metadata + + def post_update_generative_question_config( + self, response: generative_question.GenerativeQuestionConfig + ) -> generative_question.GenerativeQuestionConfig: + """Post-rpc interceptor for update_generative_question_config + + Override in a subclass to manipulate the response + after it is returned by the GenerativeQuestionService server but before + it is returned to user code. + """ + return response + + def pre_update_generative_questions_feature_config( + self, + request: generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[ + generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest, + Sequence[Tuple[str, str]], + ]: + """Pre-rpc interceptor for update_generative_questions_feature_config + + Override in a subclass to manipulate the request or metadata + before they are sent to the GenerativeQuestionService server. + """ + return request, metadata + + def post_update_generative_questions_feature_config( + self, response: generative_question.GenerativeQuestionsFeatureConfig + ) -> generative_question.GenerativeQuestionsFeatureConfig: + """Post-rpc interceptor for update_generative_questions_feature_config + + Override in a subclass to manipulate the response + after it is returned by the GenerativeQuestionService server but before + it is returned to user code. + """ + return response + + def pre_get_operation( + self, + request: operations_pb2.GetOperationRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[operations_pb2.GetOperationRequest, Sequence[Tuple[str, str]]]: + """Pre-rpc interceptor for get_operation + + Override in a subclass to manipulate the request or metadata + before they are sent to the GenerativeQuestionService server. + """ + return request, metadata + + def post_get_operation( + self, response: operations_pb2.Operation + ) -> operations_pb2.Operation: + """Post-rpc interceptor for get_operation + + Override in a subclass to manipulate the response + after it is returned by the GenerativeQuestionService server but before + it is returned to user code. + """ + return response + + def pre_list_operations( + self, + request: operations_pb2.ListOperationsRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[operations_pb2.ListOperationsRequest, Sequence[Tuple[str, str]]]: + """Pre-rpc interceptor for list_operations + + Override in a subclass to manipulate the request or metadata + before they are sent to the GenerativeQuestionService server. + """ + return request, metadata + + def post_list_operations( + self, response: operations_pb2.ListOperationsResponse + ) -> operations_pb2.ListOperationsResponse: + """Post-rpc interceptor for list_operations + + Override in a subclass to manipulate the response + after it is returned by the GenerativeQuestionService server but before + it is returned to user code. + """ + return response + + +@dataclasses.dataclass +class GenerativeQuestionServiceRestStub: + _session: AuthorizedSession + _host: str + _interceptor: GenerativeQuestionServiceRestInterceptor + + +class GenerativeQuestionServiceRestTransport(GenerativeQuestionServiceTransport): + """REST backend transport for GenerativeQuestionService. + + Service for managing LLM generated questions in search + serving. + + This class defines the same methods as the primary client, so the + primary client can load the underlying transport implementation + and call it. + + It sends JSON representations of protocol buffers over HTTP/1.1 + + """ + + def __init__( + self, + *, + host: str = "retail.googleapis.com", + credentials: Optional[ga_credentials.Credentials] = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + client_cert_source_for_mtls: Optional[Callable[[], Tuple[bytes, bytes]]] = None, + quota_project_id: Optional[str] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, + url_scheme: str = "https", + interceptor: Optional[GenerativeQuestionServiceRestInterceptor] = None, + api_audience: Optional[str] = None, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to (default: 'retail.googleapis.com'). + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + client_cert_source_for_mtls (Callable[[], Tuple[bytes, bytes]]): Client + certificate to configure mutual TLS HTTP channel. It is ignored + if ``channel`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you are developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + url_scheme: the protocol scheme for the API endpoint. Normally + "https", but for testing or local servers, + "http" can be specified. + """ + # Run the base constructor + # TODO(yon-mg): resolve other ctor params i.e. scopes, quota, etc. + # TODO: When custom host (api_endpoint) is set, `scopes` must *also* be set on the + # credentials object + maybe_url_match = re.match("^(?Phttp(?:s)?://)?(?P.*)$", host) + if maybe_url_match is None: + raise ValueError( + f"Unexpected hostname structure: {host}" + ) # pragma: NO COVER + + url_match_items = maybe_url_match.groupdict() + + host = f"{url_scheme}://{host}" if not url_match_items["scheme"] else host + + super().__init__( + host=host, + credentials=credentials, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + api_audience=api_audience, + ) + self._session = AuthorizedSession( + self._credentials, default_host=self.DEFAULT_HOST + ) + if client_cert_source_for_mtls: + self._session.configure_mtls_channel(client_cert_source_for_mtls) + self._interceptor = interceptor or GenerativeQuestionServiceRestInterceptor() + self._prep_wrapped_messages(client_info) + + class _BatchUpdateGenerativeQuestionConfigs(GenerativeQuestionServiceRestStub): + def __hash__(self): + return hash("BatchUpdateGenerativeQuestionConfigs") + + __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} + + @classmethod + def _get_unset_required_fields(cls, message_dict): + return { + k: v + for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items() + if k not in message_dict + } + + def __call__( + self, + request: generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse: + r"""Call the batch update generative + question configs method over HTTP. + + Args: + request (~.generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest): + The request object. Request for + BatchUpdateGenerativeQuestionConfig + method. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + ~.generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse: + Aggregated response for + UpdateGenerativeQuestionConfig method. + + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "post", + "uri": "/v2/{parent=projects/*/locations/*/catalogs/*}/generativeQuestion:batchUpdate", + "body": "*", + }, + ] + ( + request, + metadata, + ) = self._interceptor.pre_batch_update_generative_question_configs( + request, metadata + ) + pb_request = generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest.pb( + request + ) + transcoded_request = path_template.transcode(http_options, pb_request) + + # Jsonify the request body + + body = json_format.MessageToJson( + transcoded_request["body"], use_integers_for_enums=True + ) + uri = transcoded_request["uri"] + method = transcoded_request["method"] + + # Jsonify the query params + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + use_integers_for_enums=True, + ) + ) + query_params.update(self._get_unset_required_fields(query_params)) + + query_params["$alt"] = "json;enum-encoding=int" + + # Send the request + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(self._session, method)( + "{host}{uri}".format(host=self._host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + data=body, + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + # Return the response + resp = ( + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse() + ) + pb_resp = generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse.pb( + resp + ) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + resp = self._interceptor.post_batch_update_generative_question_configs(resp) + return resp + + class _GetGenerativeQuestionsFeatureConfig(GenerativeQuestionServiceRestStub): + def __hash__(self): + return hash("GetGenerativeQuestionsFeatureConfig") + + __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} + + @classmethod + def _get_unset_required_fields(cls, message_dict): + return { + k: v + for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items() + if k not in message_dict + } + + def __call__( + self, + request: generative_question_service.GetGenerativeQuestionsFeatureConfigRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> generative_question.GenerativeQuestionsFeatureConfig: + r"""Call the get generative questions + feature config method over HTTP. + + Args: + request (~.generative_question_service.GetGenerativeQuestionsFeatureConfigRequest): + The request object. Request for + GetGenerativeQuestionsFeatureConfig + method. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + ~.generative_question.GenerativeQuestionsFeatureConfig: + Configuration for overall generative + question feature state. + + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "get", + "uri": "/v2/{catalog=projects/*/locations/*/catalogs/*}/generativeQuestionFeature", + }, + ] + ( + request, + metadata, + ) = self._interceptor.pre_get_generative_questions_feature_config( + request, metadata + ) + pb_request = generative_question_service.GetGenerativeQuestionsFeatureConfigRequest.pb( + request + ) + transcoded_request = path_template.transcode(http_options, pb_request) + + uri = transcoded_request["uri"] + method = transcoded_request["method"] + + # Jsonify the query params + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + use_integers_for_enums=True, + ) + ) + query_params.update(self._get_unset_required_fields(query_params)) + + query_params["$alt"] = "json;enum-encoding=int" + + # Send the request + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(self._session, method)( + "{host}{uri}".format(host=self._host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + # Return the response + resp = generative_question.GenerativeQuestionsFeatureConfig() + pb_resp = generative_question.GenerativeQuestionsFeatureConfig.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + resp = self._interceptor.post_get_generative_questions_feature_config(resp) + return resp + + class _ListGenerativeQuestionConfigs(GenerativeQuestionServiceRestStub): + def __hash__(self): + return hash("ListGenerativeQuestionConfigs") + + __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} + + @classmethod + def _get_unset_required_fields(cls, message_dict): + return { + k: v + for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items() + if k not in message_dict + } + + def __call__( + self, + request: generative_question_service.ListGenerativeQuestionConfigsRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> generative_question_service.ListGenerativeQuestionConfigsResponse: + r"""Call the list generative question + configs method over HTTP. + + Args: + request (~.generative_question_service.ListGenerativeQuestionConfigsRequest): + The request object. Request for ListQuestions method. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + ~.generative_question_service.ListGenerativeQuestionConfigsResponse: + Response for ListQuestions method. + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "get", + "uri": "/v2/{parent=projects/*/locations/*/catalogs/*}/generativeQuestions", + }, + ] + request, metadata = self._interceptor.pre_list_generative_question_configs( + request, metadata + ) + pb_request = ( + generative_question_service.ListGenerativeQuestionConfigsRequest.pb( + request + ) + ) + transcoded_request = path_template.transcode(http_options, pb_request) + + uri = transcoded_request["uri"] + method = transcoded_request["method"] + + # Jsonify the query params + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + use_integers_for_enums=True, + ) + ) + query_params.update(self._get_unset_required_fields(query_params)) + + query_params["$alt"] = "json;enum-encoding=int" + + # Send the request + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(self._session, method)( + "{host}{uri}".format(host=self._host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + # Return the response + resp = generative_question_service.ListGenerativeQuestionConfigsResponse() + pb_resp = ( + generative_question_service.ListGenerativeQuestionConfigsResponse.pb( + resp + ) + ) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + resp = self._interceptor.post_list_generative_question_configs(resp) + return resp + + class _UpdateGenerativeQuestionConfig(GenerativeQuestionServiceRestStub): + def __hash__(self): + return hash("UpdateGenerativeQuestionConfig") + + __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} + + @classmethod + def _get_unset_required_fields(cls, message_dict): + return { + k: v + for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items() + if k not in message_dict + } + + def __call__( + self, + request: generative_question_service.UpdateGenerativeQuestionConfigRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> generative_question.GenerativeQuestionConfig: + r"""Call the update generative + question config method over HTTP. + + Args: + request (~.generative_question_service.UpdateGenerativeQuestionConfigRequest): + The request object. Request for + UpdateGenerativeQuestionConfig method. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + ~.generative_question.GenerativeQuestionConfig: + Configuration for a single generated + question. + + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "patch", + "uri": "/v2/{generative_question_config.catalog=projects/*/locations/*/catalogs/*}/generativeQuestion", + "body": "generative_question_config", + }, + ] + request, metadata = self._interceptor.pre_update_generative_question_config( + request, metadata + ) + pb_request = ( + generative_question_service.UpdateGenerativeQuestionConfigRequest.pb( + request + ) + ) + transcoded_request = path_template.transcode(http_options, pb_request) + + # Jsonify the request body + + body = json_format.MessageToJson( + transcoded_request["body"], use_integers_for_enums=True + ) + uri = transcoded_request["uri"] + method = transcoded_request["method"] + + # Jsonify the query params + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + use_integers_for_enums=True, + ) + ) + query_params.update(self._get_unset_required_fields(query_params)) + + query_params["$alt"] = "json;enum-encoding=int" + + # Send the request + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(self._session, method)( + "{host}{uri}".format(host=self._host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + data=body, + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + # Return the response + resp = generative_question.GenerativeQuestionConfig() + pb_resp = generative_question.GenerativeQuestionConfig.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + resp = self._interceptor.post_update_generative_question_config(resp) + return resp + + class _UpdateGenerativeQuestionsFeatureConfig(GenerativeQuestionServiceRestStub): + def __hash__(self): + return hash("UpdateGenerativeQuestionsFeatureConfig") + + __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} + + @classmethod + def _get_unset_required_fields(cls, message_dict): + return { + k: v + for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items() + if k not in message_dict + } + + def __call__( + self, + request: generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> generative_question.GenerativeQuestionsFeatureConfig: + r"""Call the update generative + questions feature config method over HTTP. + + Args: + request (~.generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest): + The request object. Request for + UpdateGenerativeQuestionsFeatureConfig + method. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + ~.generative_question.GenerativeQuestionsFeatureConfig: + Configuration for overall generative + question feature state. + + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "patch", + "uri": "/v2/{generative_questions_feature_config.catalog=projects/*/locations/*/catalogs/*}/generativeQuestionFeature", + "body": "generative_questions_feature_config", + }, + ] + ( + request, + metadata, + ) = self._interceptor.pre_update_generative_questions_feature_config( + request, metadata + ) + pb_request = generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest.pb( + request + ) + transcoded_request = path_template.transcode(http_options, pb_request) + + # Jsonify the request body + + body = json_format.MessageToJson( + transcoded_request["body"], use_integers_for_enums=True + ) + uri = transcoded_request["uri"] + method = transcoded_request["method"] + + # Jsonify the query params + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + use_integers_for_enums=True, + ) + ) + query_params.update(self._get_unset_required_fields(query_params)) + + query_params["$alt"] = "json;enum-encoding=int" + + # Send the request + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(self._session, method)( + "{host}{uri}".format(host=self._host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + data=body, + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + # Return the response + resp = generative_question.GenerativeQuestionsFeatureConfig() + pb_resp = generative_question.GenerativeQuestionsFeatureConfig.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + resp = self._interceptor.post_update_generative_questions_feature_config( + resp + ) + return resp + + @property + def batch_update_generative_question_configs( + self, + ) -> Callable[ + [generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest], + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse, + ]: + # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here. + # In C++ this would require a dynamic_cast + return self._BatchUpdateGenerativeQuestionConfigs(self._session, self._host, self._interceptor) # type: ignore + + @property + def get_generative_questions_feature_config( + self, + ) -> Callable[ + [generative_question_service.GetGenerativeQuestionsFeatureConfigRequest], + generative_question.GenerativeQuestionsFeatureConfig, + ]: + # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here. + # In C++ this would require a dynamic_cast + return self._GetGenerativeQuestionsFeatureConfig(self._session, self._host, self._interceptor) # type: ignore + + @property + def list_generative_question_configs( + self, + ) -> Callable[ + [generative_question_service.ListGenerativeQuestionConfigsRequest], + generative_question_service.ListGenerativeQuestionConfigsResponse, + ]: + # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here. + # In C++ this would require a dynamic_cast + return self._ListGenerativeQuestionConfigs(self._session, self._host, self._interceptor) # type: ignore + + @property + def update_generative_question_config( + self, + ) -> Callable[ + [generative_question_service.UpdateGenerativeQuestionConfigRequest], + generative_question.GenerativeQuestionConfig, + ]: + # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here. + # In C++ this would require a dynamic_cast + return self._UpdateGenerativeQuestionConfig(self._session, self._host, self._interceptor) # type: ignore + + @property + def update_generative_questions_feature_config( + self, + ) -> Callable[ + [generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest], + generative_question.GenerativeQuestionsFeatureConfig, + ]: + # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here. + # In C++ this would require a dynamic_cast + return self._UpdateGenerativeQuestionsFeatureConfig(self._session, self._host, self._interceptor) # type: ignore + + @property + def get_operation(self): + return self._GetOperation(self._session, self._host, self._interceptor) # type: ignore + + class _GetOperation(GenerativeQuestionServiceRestStub): + def __call__( + self, + request: operations_pb2.GetOperationRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operations_pb2.Operation: + r"""Call the get operation method over HTTP. + + Args: + request (operations_pb2.GetOperationRequest): + The request object for GetOperation method. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + operations_pb2.Operation: Response from GetOperation method. + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "get", + "uri": "/v2/{name=projects/*/locations/*/operations/*}", + }, + { + "method": "get", + "uri": "/v2/{name=projects/*/locations/*/catalogs/*/branches/*/operations/*}", + }, + { + "method": "get", + "uri": "/v2/{name=projects/*/locations/*/catalogs/*/operations/*}", + }, + { + "method": "get", + "uri": "/v2/{name=projects/*/operations/*}", + }, + ] + + request, metadata = self._interceptor.pre_get_operation(request, metadata) + request_kwargs = json_format.MessageToDict(request) + transcoded_request = path_template.transcode(http_options, **request_kwargs) + + uri = transcoded_request["uri"] + method = transcoded_request["method"] + + # Jsonify the query params + query_params = json.loads(json.dumps(transcoded_request["query_params"])) + + # Send the request + headers = dict(metadata) + headers["Content-Type"] = "application/json" + + response = getattr(self._session, method)( + "{host}{uri}".format(host=self._host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params), + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + resp = operations_pb2.Operation() + resp = json_format.Parse(response.content.decode("utf-8"), resp) + resp = self._interceptor.post_get_operation(resp) + return resp + + @property + def list_operations(self): + return self._ListOperations(self._session, self._host, self._interceptor) # type: ignore + + class _ListOperations(GenerativeQuestionServiceRestStub): + def __call__( + self, + request: operations_pb2.ListOperationsRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operations_pb2.ListOperationsResponse: + r"""Call the list operations method over HTTP. + + Args: + request (operations_pb2.ListOperationsRequest): + The request object for ListOperations method. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + operations_pb2.ListOperationsResponse: Response from ListOperations method. + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "get", + "uri": "/v2/{name=projects/*/locations/*}/operations", + }, + { + "method": "get", + "uri": "/v2/{name=projects/*/locations/*/catalogs/*}/operations", + }, + { + "method": "get", + "uri": "/v2/{name=projects/*}/operations", + }, + ] + + request, metadata = self._interceptor.pre_list_operations(request, metadata) + request_kwargs = json_format.MessageToDict(request) + transcoded_request = path_template.transcode(http_options, **request_kwargs) + + uri = transcoded_request["uri"] + method = transcoded_request["method"] + + # Jsonify the query params + query_params = json.loads(json.dumps(transcoded_request["query_params"])) + + # Send the request + headers = dict(metadata) + headers["Content-Type"] = "application/json" + + response = getattr(self._session, method)( + "{host}{uri}".format(host=self._host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params), + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + resp = operations_pb2.ListOperationsResponse() + resp = json_format.Parse(response.content.decode("utf-8"), resp) + resp = self._interceptor.post_list_operations(resp) + return resp + + @property + def kind(self) -> str: + return "rest" + + def close(self): + self._session.close() + + +__all__ = ("GenerativeQuestionServiceRestTransport",) diff --git a/packages/google-cloud-retail/google/cloud/retail_v2/types/__init__.py b/packages/google-cloud-retail/google/cloud/retail_v2/types/__init__.py index 8ac7d937c80f..c079fa59afb4 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2/types/__init__.py +++ b/packages/google-cloud-retail/google/cloud/retail_v2/types/__init__.py @@ -73,6 +73,19 @@ OutputConfig, OutputResult, ) +from .generative_question import ( + GenerativeQuestionConfig, + GenerativeQuestionsFeatureConfig, +) +from .generative_question_service import ( + BatchUpdateGenerativeQuestionConfigsRequest, + BatchUpdateGenerativeQuestionConfigsResponse, + GetGenerativeQuestionsFeatureConfigRequest, + ListGenerativeQuestionConfigsRequest, + ListGenerativeQuestionConfigsResponse, + UpdateGenerativeQuestionConfigRequest, + UpdateGenerativeQuestionsFeatureConfigRequest, +) from .import_config import ( BigQuerySource, CompletionDataInputConfig, @@ -140,7 +153,14 @@ PurgeUserEventsRequest, PurgeUserEventsResponse, ) -from .search_service import ExperimentInfo, SearchRequest, SearchResponse +from .search_service import ( + ExperimentInfo, + ProductAttributeInterval, + ProductAttributeValue, + SearchRequest, + SearchResponse, + Tile, +) from .serving_config import ServingConfig from .serving_config_service import ( AddControlRequest, @@ -213,6 +233,15 @@ "GcsOutputResult", "OutputConfig", "OutputResult", + "GenerativeQuestionConfig", + "GenerativeQuestionsFeatureConfig", + "BatchUpdateGenerativeQuestionConfigsRequest", + "BatchUpdateGenerativeQuestionConfigsResponse", + "GetGenerativeQuestionsFeatureConfigRequest", + "ListGenerativeQuestionConfigsRequest", + "ListGenerativeQuestionConfigsResponse", + "UpdateGenerativeQuestionConfigRequest", + "UpdateGenerativeQuestionsFeatureConfigRequest", "BigQuerySource", "CompletionDataInputConfig", "GcsSource", @@ -274,8 +303,11 @@ "PurgeUserEventsRequest", "PurgeUserEventsResponse", "ExperimentInfo", + "ProductAttributeInterval", + "ProductAttributeValue", "SearchRequest", "SearchResponse", + "Tile", "ServingConfig", "AddControlRequest", "CreateServingConfigRequest", diff --git a/packages/google-cloud-retail/google/cloud/retail_v2/types/common.py b/packages/google-cloud-retail/google/cloud/retail_v2/types/common.py index 5f0ffcdcb277..f79f4ecf8887 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2/types/common.py +++ b/packages/google-cloud-retail/google/cloud/retail_v2/types/common.py @@ -543,7 +543,7 @@ class ForceReturnFacetAction(proto.Message): facet_position_adjustments (MutableSequence[google.cloud.retail_v2.types.Rule.ForceReturnFacetAction.FacetPositionAdjustment]): Each instance corresponds to a force return attribute for the given condition. There can't - be more 3 instances here. + be more 15 instances here. """ class FacetPositionAdjustment(proto.Message): diff --git a/packages/google-cloud-retail/google/cloud/retail_v2/types/completion_service.py b/packages/google-cloud-retail/google/cloud/retail_v2/types/completion_service.py index 50c5a03a1ce6..b3deb5ffc7fe 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2/types/completion_service.py +++ b/packages/google-cloud-retail/google/cloud/retail_v2/types/completion_service.py @@ -108,9 +108,9 @@ class CompleteQueryRequest(proto.Message): higher, it will be capped by 20. enable_attribute_suggestions (bool): If true, attribute suggestions are enabled - and provided in response. - This field is only available for "cloud-retail" - dataset. + and provided in the response. + This field is only available for the + "cloud-retail" dataset. entity (str): The entity for customers who run multiple entities, domains, sites, or regions, for example, ``Google US``, @@ -195,6 +195,15 @@ class CompleteQueryResponse(proto.Message): Recent searches are deduplicated. More recent searches will be reserved when duplication happens. + attribute_results (MutableMapping[str, google.cloud.retail_v2.types.CompleteQueryResponse.AttributeResult]): + A map of matched attribute suggestions. This field is only + available for "cloud-retail" dataset. + + Current supported keys: + + - ``brands`` + + - ``categories`` """ class CompletionResult(proto.Message): @@ -239,6 +248,20 @@ class RecentSearchResult(proto.Message): number=1, ) + class AttributeResult(proto.Message): + r"""Resource that represents attribute results. + The list of suggestions for the attribute. + + Attributes: + suggestions (MutableSequence[str]): + + """ + + suggestions: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=1, + ) + completion_results: MutableSequence[CompletionResult] = proto.RepeatedField( proto.MESSAGE, number=1, @@ -253,6 +276,12 @@ class RecentSearchResult(proto.Message): number=3, message=RecentSearchResult, ) + attribute_results: MutableMapping[str, AttributeResult] = proto.MapField( + proto.STRING, + proto.MESSAGE, + number=4, + message=AttributeResult, + ) __all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/packages/google-cloud-retail/google/cloud/retail_v2/types/generative_question.py b/packages/google-cloud-retail/google/cloud/retail_v2/types/generative_question.py new file mode 100644 index 000000000000..38cfc85dd855 --- /dev/null +++ b/packages/google-cloud-retail/google/cloud/retail_v2/types/generative_question.py @@ -0,0 +1,122 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + +from typing import MutableMapping, MutableSequence + +import proto # type: ignore + +__protobuf__ = proto.module( + package="google.cloud.retail.v2", + manifest={ + "GenerativeQuestionsFeatureConfig", + "GenerativeQuestionConfig", + }, +) + + +class GenerativeQuestionsFeatureConfig(proto.Message): + r"""Configuration for overall generative question feature state. + + Attributes: + catalog (str): + Required. Resource name of the affected + catalog. Format: + projects/{project}/locations/{location}/catalogs/{catalog} + feature_enabled (bool): + Optional. Determines whether questions will + be used at serving time. Note: This feature + cannot be enabled until initial data + requirements are satisfied. + minimum_products (int): + Optional. Minimum number of products in the + response to trigger follow-up questions. Value + must be 0 or positive. + """ + + catalog: str = proto.Field( + proto.STRING, + number=1, + ) + feature_enabled: bool = proto.Field( + proto.BOOL, + number=2, + ) + minimum_products: int = proto.Field( + proto.INT32, + number=3, + ) + + +class GenerativeQuestionConfig(proto.Message): + r"""Configuration for a single generated question. + + Attributes: + catalog (str): + Required. Resource name of the catalog. + Format: + projects/{project}/locations/{location}/catalogs/{catalog} + facet (str): + Required. The facet to which the question is + associated. + generated_question (str): + Output only. The LLM generated question. + final_question (str): + Optional. The question that will be used at serving time. + Question can have a max length of 300 bytes. When not + populated, generated_question should be used. + example_values (MutableSequence[str]): + Output only. Values that can be used to + answer the question. + frequency (float): + Output only. The ratio of how often a + question was asked. + allowed_in_conversation (bool): + Optional. Whether the question is asked at + serving time. + """ + + catalog: str = proto.Field( + proto.STRING, + number=1, + ) + facet: str = proto.Field( + proto.STRING, + number=2, + ) + generated_question: str = proto.Field( + proto.STRING, + number=3, + ) + final_question: str = proto.Field( + proto.STRING, + number=4, + ) + example_values: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=5, + ) + frequency: float = proto.Field( + proto.FLOAT, + number=6, + ) + allowed_in_conversation: bool = proto.Field( + proto.BOOL, + number=7, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/packages/google-cloud-retail/google/cloud/retail_v2/types/generative_question_service.py b/packages/google-cloud-retail/google/cloud/retail_v2/types/generative_question_service.py new file mode 100644 index 000000000000..effeab1bb5b8 --- /dev/null +++ b/packages/google-cloud-retail/google/cloud/retail_v2/types/generative_question_service.py @@ -0,0 +1,187 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + +from typing import MutableMapping, MutableSequence + +from google.protobuf import field_mask_pb2 # type: ignore +import proto # type: ignore + +from google.cloud.retail_v2.types import generative_question + +__protobuf__ = proto.module( + package="google.cloud.retail.v2", + manifest={ + "UpdateGenerativeQuestionsFeatureConfigRequest", + "GetGenerativeQuestionsFeatureConfigRequest", + "ListGenerativeQuestionConfigsRequest", + "ListGenerativeQuestionConfigsResponse", + "UpdateGenerativeQuestionConfigRequest", + "BatchUpdateGenerativeQuestionConfigsRequest", + "BatchUpdateGenerativeQuestionConfigsResponse", + }, +) + + +class UpdateGenerativeQuestionsFeatureConfigRequest(proto.Message): + r"""Request for UpdateGenerativeQuestionsFeatureConfig method. + + Attributes: + generative_questions_feature_config (google.cloud.retail_v2.types.GenerativeQuestionsFeatureConfig): + Required. The configuration managing the + feature state. + update_mask (google.protobuf.field_mask_pb2.FieldMask): + Optional. Indicates which fields in the provided + [GenerativeQuestionsFeatureConfig][google.cloud.retail.v2.GenerativeQuestionsFeatureConfig] + to update. If not set or empty, all supported fields are + updated. + """ + + generative_questions_feature_config: generative_question.GenerativeQuestionsFeatureConfig = proto.Field( + proto.MESSAGE, + number=2, + message=generative_question.GenerativeQuestionsFeatureConfig, + ) + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=4, + message=field_mask_pb2.FieldMask, + ) + + +class GetGenerativeQuestionsFeatureConfigRequest(proto.Message): + r"""Request for GetGenerativeQuestionsFeatureConfig method. + + Attributes: + catalog (str): + Required. Resource name of the parent + catalog. Format: + projects/{project}/locations/{location}/catalogs/{catalog} + """ + + catalog: str = proto.Field( + proto.STRING, + number=1, + ) + + +class ListGenerativeQuestionConfigsRequest(proto.Message): + r"""Request for ListQuestions method. + + Attributes: + parent (str): + Required. Resource name of the parent + catalog. Format: + projects/{project}/locations/{location}/catalogs/{catalog} + """ + + parent: str = proto.Field( + proto.STRING, + number=1, + ) + + +class ListGenerativeQuestionConfigsResponse(proto.Message): + r"""Response for ListQuestions method. + + Attributes: + generative_question_configs (MutableSequence[google.cloud.retail_v2.types.GenerativeQuestionConfig]): + All the questions for a given catalog. + """ + + generative_question_configs: MutableSequence[ + generative_question.GenerativeQuestionConfig + ] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message=generative_question.GenerativeQuestionConfig, + ) + + +class UpdateGenerativeQuestionConfigRequest(proto.Message): + r"""Request for UpdateGenerativeQuestionConfig method. + + Attributes: + generative_question_config (google.cloud.retail_v2.types.GenerativeQuestionConfig): + Required. The question to update. + update_mask (google.protobuf.field_mask_pb2.FieldMask): + Optional. Indicates which fields in the provided + [GenerativeQuestionConfig][google.cloud.retail.v2.GenerativeQuestionConfig] + to update. The following are NOT supported: + + - [GenerativeQuestionConfig.frequency][google.cloud.retail.v2.GenerativeQuestionConfig.frequency] + + If not set or empty, all supported fields are updated. + """ + + generative_question_config: generative_question.GenerativeQuestionConfig = ( + proto.Field( + proto.MESSAGE, + number=3, + message=generative_question.GenerativeQuestionConfig, + ) + ) + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=4, + message=field_mask_pb2.FieldMask, + ) + + +class BatchUpdateGenerativeQuestionConfigsRequest(proto.Message): + r"""Request for BatchUpdateGenerativeQuestionConfig method. + + Attributes: + parent (str): + Optional. Resource name of the parent + catalog. Format: + projects/{project}/locations/{location}/catalogs/{catalog} + requests (MutableSequence[google.cloud.retail_v2.types.UpdateGenerativeQuestionConfigRequest]): + Required. The updates question configs. + """ + + parent: str = proto.Field( + proto.STRING, + number=1, + ) + requests: MutableSequence[ + "UpdateGenerativeQuestionConfigRequest" + ] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="UpdateGenerativeQuestionConfigRequest", + ) + + +class BatchUpdateGenerativeQuestionConfigsResponse(proto.Message): + r"""Aggregated response for UpdateGenerativeQuestionConfig + method. + + Attributes: + generative_question_configs (MutableSequence[google.cloud.retail_v2.types.GenerativeQuestionConfig]): + Optional. The updates question configs. + """ + + generative_question_configs: MutableSequence[ + generative_question.GenerativeQuestionConfig + ] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message=generative_question.GenerativeQuestionConfig, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/packages/google-cloud-retail/google/cloud/retail_v2/types/product.py b/packages/google-cloud-retail/google/cloud/retail_v2/types/product.py index 433773fb7714..61a5ed6832d5 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2/types/product.py +++ b/packages/google-cloud-retail/google/cloud/retail_v2/types/product.py @@ -345,6 +345,16 @@ class Product(proto.Message): [Product][google.cloud.retail.v2.Product]. Default to [Availability.IN_STOCK][google.cloud.retail.v2.Product.Availability.IN_STOCK]. + For primary products with variants set the availability of + the primary as + [Availability.OUT_OF_STOCK][google.cloud.retail.v2.Product.Availability.OUT_OF_STOCK] + and set the true availability at the variant level. This way + the primary product will be considered "in stock" as long as + it has at least one variant in stock. + + For primary products with no variants set the true + availability at the primary level. + Corresponding properties: Google Merchant Center property `availability `__. Schema.org property @@ -532,9 +542,6 @@ class Product(proto.Message): - [name][google.cloud.retail.v2.Product.name] - [color_info][google.cloud.retail.v2.Product.color_info] - The maximum number of paths is 30. Otherwise, an - INVALID_ARGUMENT error is returned. - Note: Returning more fields in [SearchResponse][google.cloud.retail.v2.SearchResponse] can increase response payload size and serving latency. diff --git a/packages/google-cloud-retail/google/cloud/retail_v2/types/search_service.py b/packages/google-cloud-retail/google/cloud/retail_v2/types/search_service.py index f08b624defdb..c67bf0dffabc 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2/types/search_service.py +++ b/packages/google-cloud-retail/google/cloud/retail_v2/types/search_service.py @@ -27,6 +27,9 @@ __protobuf__ = proto.module( package="google.cloud.retail.v2", manifest={ + "ProductAttributeValue", + "ProductAttributeInterval", + "Tile", "SearchRequest", "SearchResponse", "ExperimentInfo", @@ -34,6 +37,93 @@ ) +class ProductAttributeValue(proto.Message): + r"""Product attribute which structured by an attribute name and value. + This structure is used in conversational search filters and answers. + For example, if we have ``name=color`` and ``value=red``, this means + that the color is ``red``. + + Attributes: + name (str): + The attribute name. + value (str): + The attribute value. + """ + + name: str = proto.Field( + proto.STRING, + number=1, + ) + value: str = proto.Field( + proto.STRING, + number=2, + ) + + +class ProductAttributeInterval(proto.Message): + r"""Product attribute name and numeric interval. + + Attributes: + name (str): + The attribute name (e.g. "length") + interval (google.cloud.retail_v2.types.Interval): + The numeric interval (e.g. [10, 20)) + """ + + name: str = proto.Field( + proto.STRING, + number=1, + ) + interval: common.Interval = proto.Field( + proto.MESSAGE, + number=2, + message=common.Interval, + ) + + +class Tile(proto.Message): + r"""This field specifies the tile information including an + attribute key, attribute value. More fields will be added in the + future, eg: product id or product counts, etc. + + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + product_attribute_value (google.cloud.retail_v2.types.ProductAttributeValue): + The product attribute key-value. + + This field is a member of `oneof`_ ``product_attribute``. + product_attribute_interval (google.cloud.retail_v2.types.ProductAttributeInterval): + The product attribute key-numeric interval. + + This field is a member of `oneof`_ ``product_attribute``. + representative_product_id (str): + The representative product id for this tile. + """ + + product_attribute_value: "ProductAttributeValue" = proto.Field( + proto.MESSAGE, + number=1, + oneof="product_attribute", + message="ProductAttributeValue", + ) + product_attribute_interval: "ProductAttributeInterval" = proto.Field( + proto.MESSAGE, + number=2, + oneof="product_attribute", + message="ProductAttributeInterval", + ) + representative_product_id: str = proto.Field( + proto.STRING, + number=3, + ) + + class SearchRequest(proto.Message): r"""Request message for [SearchService.Search][google.cloud.retail.v2.SearchService.Search] @@ -321,6 +411,13 @@ class SearchRequest(proto.Message): matched with [UserEvent.entity][google.cloud.retail.v2.UserEvent.entity] to get search results boosted by entity. + conversational_search_spec (google.cloud.retail_v2.types.SearchRequest.ConversationalSearchSpec): + Optional. This field specifies all + conversational related parameters addition to + traditional retail search. + tile_navigation_spec (google.cloud.retail_v2.types.SearchRequest.TileNavigationSpec): + Optional. This field specifies tile + navigation related parameters. """ class SearchMode(proto.Enum): @@ -902,6 +999,135 @@ class Mode(proto.Enum): enum="SearchRequest.SpellCorrectionSpec.Mode", ) + class ConversationalSearchSpec(proto.Message): + r"""This field specifies all conversational related parameters + addition to traditional retail search. + + Attributes: + followup_conversation_requested (bool): + This field specifies whether the customer + would like to do conversational search. If this + field is set to true, conversational related + extra information will be returned from server + side, including follow-up question, answer + options, etc. + conversation_id (str): + This field specifies the conversation id, which maintains + the state of the conversation between client side and server + side. Use the value from the previous + [ConversationalSearchResult.conversation_id][]. For the + initial request, this should be empty. + user_answer (google.cloud.retail_v2.types.SearchRequest.ConversationalSearchSpec.UserAnswer): + This field specifies the current user answer + during the conversational search. This can be + either user selected from suggested answers or + user input plain text. + """ + + class UserAnswer(proto.Message): + r"""This field specifies the current user answer during the + conversational search. This can be either user selected from + suggested answers or user input plain text. + + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + text_answer (str): + This field specifies the incremental input + text from the user during the conversational + search. + + This field is a member of `oneof`_ ``type``. + selected_answer (google.cloud.retail_v2.types.SearchRequest.ConversationalSearchSpec.UserAnswer.SelectedAnswer): + This field specifies the selected attributes during the + conversational search. This should be a subset of + [ConversationalSearchResult.suggested_answers][]. + + This field is a member of `oneof`_ ``type``. + """ + + class SelectedAnswer(proto.Message): + r"""This field specifies the selected answers during the + conversational search. + + Attributes: + product_attribute_values (MutableSequence[google.cloud.retail_v2.types.ProductAttributeValue]): + This field is deprecated and should not be + set. + product_attribute_value (google.cloud.retail_v2.types.ProductAttributeValue): + This field specifies the selected answer + which is a attribute key-value. + """ + + product_attribute_values: MutableSequence[ + "ProductAttributeValue" + ] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="ProductAttributeValue", + ) + product_attribute_value: "ProductAttributeValue" = proto.Field( + proto.MESSAGE, + number=2, + message="ProductAttributeValue", + ) + + text_answer: str = proto.Field( + proto.STRING, + number=1, + oneof="type", + ) + selected_answer: "SearchRequest.ConversationalSearchSpec.UserAnswer.SelectedAnswer" = proto.Field( + proto.MESSAGE, + number=2, + oneof="type", + message="SearchRequest.ConversationalSearchSpec.UserAnswer.SelectedAnswer", + ) + + followup_conversation_requested: bool = proto.Field( + proto.BOOL, + number=1, + ) + conversation_id: str = proto.Field( + proto.STRING, + number=2, + ) + user_answer: "SearchRequest.ConversationalSearchSpec.UserAnswer" = proto.Field( + proto.MESSAGE, + number=3, + message="SearchRequest.ConversationalSearchSpec.UserAnswer", + ) + + class TileNavigationSpec(proto.Message): + r"""This field specifies tile navigation related parameters. + + Attributes: + tile_navigation_requested (bool): + This field specifies whether the customer + would like to request tile navigation. + applied_tiles (MutableSequence[google.cloud.retail_v2.types.Tile]): + This field specifies the tiles which are already clicked in + client side. NOTE: This field is not being used for + filtering search products. Client side should also put all + the applied tiles in + [SearchRequest.filter][google.cloud.retail.v2.SearchRequest.filter]. + """ + + tile_navigation_requested: bool = proto.Field( + proto.BOOL, + number=1, + ) + applied_tiles: MutableSequence["Tile"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="Tile", + ) + placement: str = proto.Field( proto.STRING, number=1, @@ -1000,6 +1226,16 @@ class Mode(proto.Enum): proto.STRING, number=38, ) + conversational_search_spec: ConversationalSearchSpec = proto.Field( + proto.MESSAGE, + number=40, + message=ConversationalSearchSpec, + ) + tile_navigation_spec: TileNavigationSpec = proto.Field( + proto.MESSAGE, + number=41, + message=TileNavigationSpec, + ) class SearchResponse(proto.Message): @@ -1056,6 +1292,14 @@ class SearchResponse(proto.Message): Metadata related to A/B testing [Experiment][] associated with this response. Only exists when an experiment is triggered. + conversational_search_result (google.cloud.retail_v2.types.SearchResponse.ConversationalSearchResult): + This field specifies all related information + that is needed on client side for UI rendering + of conversational retail search. + tile_navigation_result (google.cloud.retail_v2.types.SearchResponse.TileNavigationResult): + This field specifies all related information + for tile navigation that will be used in client + side. """ class SearchResult(proto.Message): @@ -1302,6 +1546,126 @@ class QueryExpansionInfo(proto.Message): number=2, ) + class ConversationalSearchResult(proto.Message): + r"""This field specifies all related information that is needed + on client side for UI rendering of conversational retail search. + + Attributes: + conversation_id (str): + Conversation UUID. This field will be stored in client side + storage to maintain the conversation session with server and + will be used for next search request's + [SearchRequest.ConversationalSearchSpec.conversation_id][google.cloud.retail.v2.SearchRequest.ConversationalSearchSpec.conversation_id] + to restore conversation state in server. + refined_query (str): + The current refined query for the conversational search. + This field will be used in customer UI that the query in the + search bar should be replaced with the refined query. For + example, if + [SearchRequest.query][google.cloud.retail.v2.SearchRequest.query] + is ``dress`` and next + [SearchRequest.ConversationalSearchSpec.UserAnswer.text_answer][google.cloud.retail.v2.SearchRequest.ConversationalSearchSpec.UserAnswer.text_answer] + is ``red color``, which does not match any product attribute + value filters, the refined query will be + ``dress, red color``. + additional_filters (MutableSequence[google.cloud.retail_v2.types.SearchResponse.ConversationalSearchResult.AdditionalFilter]): + This field is deprecated but will be kept for backward + compatibility. There is expected to have only one additional + filter and the value will be the same to the same as field + ``additional_filter``. + followup_question (str): + The follow-up question. e.g., ``What is the color?`` + suggested_answers (MutableSequence[google.cloud.retail_v2.types.SearchResponse.ConversationalSearchResult.SuggestedAnswer]): + The answer options provided to client for the + follow-up question. + additional_filter (google.cloud.retail_v2.types.SearchResponse.ConversationalSearchResult.AdditionalFilter): + This is the incremental additional filters implied from the + current user answer. User should add the suggested addition + filters to the previous + [SearchRequest.filter][google.cloud.retail.v2.SearchRequest.filter], + and use the merged filter in the follow up search request. + """ + + class SuggestedAnswer(proto.Message): + r"""Suggested answers to the follow-up question. + + Attributes: + product_attribute_value (google.cloud.retail_v2.types.ProductAttributeValue): + Product attribute value, including an + attribute key and an attribute value. Other + types can be added here in the future. + """ + + product_attribute_value: "ProductAttributeValue" = proto.Field( + proto.MESSAGE, + number=1, + message="ProductAttributeValue", + ) + + class AdditionalFilter(proto.Message): + r"""Additional filter that client side need to apply. + + Attributes: + product_attribute_value (google.cloud.retail_v2.types.ProductAttributeValue): + Product attribute value, including an + attribute key and an attribute value. Other + types can be added here in the future. + """ + + product_attribute_value: "ProductAttributeValue" = proto.Field( + proto.MESSAGE, + number=1, + message="ProductAttributeValue", + ) + + conversation_id: str = proto.Field( + proto.STRING, + number=1, + ) + refined_query: str = proto.Field( + proto.STRING, + number=2, + ) + additional_filters: MutableSequence[ + "SearchResponse.ConversationalSearchResult.AdditionalFilter" + ] = proto.RepeatedField( + proto.MESSAGE, + number=3, + message="SearchResponse.ConversationalSearchResult.AdditionalFilter", + ) + followup_question: str = proto.Field( + proto.STRING, + number=4, + ) + suggested_answers: MutableSequence[ + "SearchResponse.ConversationalSearchResult.SuggestedAnswer" + ] = proto.RepeatedField( + proto.MESSAGE, + number=5, + message="SearchResponse.ConversationalSearchResult.SuggestedAnswer", + ) + additional_filter: "SearchResponse.ConversationalSearchResult.AdditionalFilter" = proto.Field( + proto.MESSAGE, + number=6, + message="SearchResponse.ConversationalSearchResult.AdditionalFilter", + ) + + class TileNavigationResult(proto.Message): + r"""This field specifies all related information for tile + navigation that will be used in client side. + + Attributes: + tiles (MutableSequence[google.cloud.retail_v2.types.Tile]): + The current tiles that are used for tile + navigation, sorted by engagement. + """ + + tiles: MutableSequence["Tile"] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="Tile", + ) + @property def raw_page(self): return self @@ -1357,6 +1721,16 @@ def raw_page(self): number=17, message="ExperimentInfo", ) + conversational_search_result: ConversationalSearchResult = proto.Field( + proto.MESSAGE, + number=18, + message=ConversationalSearchResult, + ) + tile_navigation_result: TileNavigationResult = proto.Field( + proto.MESSAGE, + number=19, + message=TileNavigationResult, + ) class ExperimentInfo(proto.Message): diff --git a/packages/google-cloud-retail/google/cloud/retail_v2alpha/__init__.py b/packages/google-cloud-retail/google/cloud/retail_v2alpha/__init__.py index be8e3e66a81b..be0c3e836a59 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2alpha/__init__.py +++ b/packages/google-cloud-retail/google/cloud/retail_v2alpha/__init__.py @@ -29,6 +29,10 @@ CompletionServiceClient, ) from .services.control_service import ControlServiceAsyncClient, ControlServiceClient +from .services.generative_question_service import ( + GenerativeQuestionServiceAsyncClient, + GenerativeQuestionServiceClient, +) from .services.merchant_center_account_link_service import ( MerchantCenterAccountLinkServiceAsyncClient, MerchantCenterAccountLinkServiceClient, @@ -116,12 +120,27 @@ ExportAnalyticsMetricsResponse, ExportErrorsConfig, ExportMetadata, + ExportProductsRequest, ExportProductsResponse, + ExportUserEventsRequest, ExportUserEventsResponse, GcsOutputResult, OutputConfig, OutputResult, ) +from .types.generative_question import ( + GenerativeQuestionConfig, + GenerativeQuestionsFeatureConfig, +) +from .types.generative_question_service import ( + BatchUpdateGenerativeQuestionConfigsRequest, + BatchUpdateGenerativeQuestionConfigsResponse, + GetGenerativeQuestionsFeatureConfigRequest, + ListGenerativeQuestionConfigsRequest, + ListGenerativeQuestionConfigsResponse, + UpdateGenerativeQuestionConfigRequest, + UpdateGenerativeQuestionsFeatureConfigRequest, +) from .types.import_config import ( BigQuerySource, CompletionDataInputConfig, @@ -214,7 +233,14 @@ PurgeUserEventsRequest, PurgeUserEventsResponse, ) -from .types.search_service import ExperimentInfo, SearchRequest, SearchResponse +from .types.search_service import ( + ExperimentInfo, + ProductAttributeInterval, + ProductAttributeValue, + SearchRequest, + SearchResponse, + Tile, +) from .types.serving_config import ServingConfig from .types.serving_config_service import ( AddControlRequest, @@ -246,6 +272,7 @@ "CatalogServiceAsyncClient", "CompletionServiceAsyncClient", "ControlServiceAsyncClient", + "GenerativeQuestionServiceAsyncClient", "MerchantCenterAccountLinkServiceAsyncClient", "ModelServiceAsyncClient", "PredictionServiceAsyncClient", @@ -270,6 +297,8 @@ "Audience", "BatchRemoveCatalogAttributesRequest", "BatchRemoveCatalogAttributesResponse", + "BatchUpdateGenerativeQuestionConfigsRequest", + "BatchUpdateGenerativeQuestionConfigsResponse", "BigQueryOutputResult", "BigQuerySource", "Branch", @@ -310,11 +339,16 @@ "ExportAnalyticsMetricsResponse", "ExportErrorsConfig", "ExportMetadata", + "ExportProductsRequest", "ExportProductsResponse", + "ExportUserEventsRequest", "ExportUserEventsResponse", "FulfillmentInfo", "GcsOutputResult", "GcsSource", + "GenerativeQuestionConfig", + "GenerativeQuestionServiceClient", + "GenerativeQuestionsFeatureConfig", "GetAlertConfigRequest", "GetAttributesConfigRequest", "GetBranchRequest", @@ -322,6 +356,7 @@ "GetControlRequest", "GetDefaultBranchRequest", "GetDefaultBranchResponse", + "GetGenerativeQuestionsFeatureConfigRequest", "GetLoggingConfigRequest", "GetModelRequest", "GetProductRequest", @@ -345,6 +380,8 @@ "ListControlsResponse", "ListEnrolledSolutionsRequest", "ListEnrolledSolutionsResponse", + "ListGenerativeQuestionConfigsRequest", + "ListGenerativeQuestionConfigsResponse", "ListMerchantCenterAccountLinksRequest", "ListMerchantCenterAccountLinksResponse", "ListModelsRequest", @@ -370,6 +407,8 @@ "PredictionServiceClient", "PriceInfo", "Product", + "ProductAttributeInterval", + "ProductAttributeValue", "ProductDetail", "ProductInlineSource", "ProductInputConfig", @@ -412,6 +451,7 @@ "SetInventoryRequest", "SetInventoryResponse", "SolutionType", + "Tile", "TransformedUserEventsMetadata", "TuneModelMetadata", "TuneModelRequest", @@ -421,6 +461,8 @@ "UpdateCatalogRequest", "UpdateCompletionConfigRequest", "UpdateControlRequest", + "UpdateGenerativeQuestionConfigRequest", + "UpdateGenerativeQuestionsFeatureConfigRequest", "UpdateLoggingConfigRequest", "UpdateModelRequest", "UpdateProductRequest", diff --git a/packages/google-cloud-retail/google/cloud/retail_v2alpha/gapic_metadata.json b/packages/google-cloud-retail/google/cloud/retail_v2alpha/gapic_metadata.json index ae379f6da49b..7f1396236dd9 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2alpha/gapic_metadata.json +++ b/packages/google-cloud-retail/google/cloud/retail_v2alpha/gapic_metadata.json @@ -430,6 +430,100 @@ } } }, + "GenerativeQuestionService": { + "clients": { + "grpc": { + "libraryClient": "GenerativeQuestionServiceClient", + "rpcs": { + "BatchUpdateGenerativeQuestionConfigs": { + "methods": [ + "batch_update_generative_question_configs" + ] + }, + "GetGenerativeQuestionsFeatureConfig": { + "methods": [ + "get_generative_questions_feature_config" + ] + }, + "ListGenerativeQuestionConfigs": { + "methods": [ + "list_generative_question_configs" + ] + }, + "UpdateGenerativeQuestionConfig": { + "methods": [ + "update_generative_question_config" + ] + }, + "UpdateGenerativeQuestionsFeatureConfig": { + "methods": [ + "update_generative_questions_feature_config" + ] + } + } + }, + "grpc-async": { + "libraryClient": "GenerativeQuestionServiceAsyncClient", + "rpcs": { + "BatchUpdateGenerativeQuestionConfigs": { + "methods": [ + "batch_update_generative_question_configs" + ] + }, + "GetGenerativeQuestionsFeatureConfig": { + "methods": [ + "get_generative_questions_feature_config" + ] + }, + "ListGenerativeQuestionConfigs": { + "methods": [ + "list_generative_question_configs" + ] + }, + "UpdateGenerativeQuestionConfig": { + "methods": [ + "update_generative_question_config" + ] + }, + "UpdateGenerativeQuestionsFeatureConfig": { + "methods": [ + "update_generative_questions_feature_config" + ] + } + } + }, + "rest": { + "libraryClient": "GenerativeQuestionServiceClient", + "rpcs": { + "BatchUpdateGenerativeQuestionConfigs": { + "methods": [ + "batch_update_generative_question_configs" + ] + }, + "GetGenerativeQuestionsFeatureConfig": { + "methods": [ + "get_generative_questions_feature_config" + ] + }, + "ListGenerativeQuestionConfigs": { + "methods": [ + "list_generative_question_configs" + ] + }, + "UpdateGenerativeQuestionConfig": { + "methods": [ + "update_generative_question_config" + ] + }, + "UpdateGenerativeQuestionsFeatureConfig": { + "methods": [ + "update_generative_questions_feature_config" + ] + } + } + } + } + }, "MerchantCenterAccountLinkService": { "clients": { "grpc": { @@ -692,6 +786,11 @@ "delete_product" ] }, + "ExportProducts": { + "methods": [ + "export_products" + ] + }, "GetProduct": { "methods": [ "get_product" @@ -757,6 +856,11 @@ "delete_product" ] }, + "ExportProducts": { + "methods": [ + "export_products" + ] + }, "GetProduct": { "methods": [ "get_product" @@ -822,6 +926,11 @@ "delete_product" ] }, + "ExportProducts": { + "methods": [ + "export_products" + ] + }, "GetProduct": { "methods": [ "get_product" @@ -1173,6 +1282,11 @@ "collect_user_event" ] }, + "ExportUserEvents": { + "methods": [ + "export_user_events" + ] + }, "ImportUserEvents": { "methods": [ "import_user_events" @@ -1203,6 +1317,11 @@ "collect_user_event" ] }, + "ExportUserEvents": { + "methods": [ + "export_user_events" + ] + }, "ImportUserEvents": { "methods": [ "import_user_events" @@ -1233,6 +1352,11 @@ "collect_user_event" ] }, + "ExportUserEvents": { + "methods": [ + "export_user_events" + ] + }, "ImportUserEvents": { "methods": [ "import_user_events" diff --git a/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/branch_service/async_client.py b/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/branch_service/async_client.py index 7ffaac9b7e02..eb3991f294a3 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/branch_service/async_client.py +++ b/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/branch_service/async_client.py @@ -277,9 +277,9 @@ async def list_branches( timeout: Union[float, object] = gapic_v1.method.DEFAULT, metadata: Sequence[Tuple[str, str]] = (), ) -> branch_service.ListBranchesResponse: - r"""Lists all [Branch][google.cloud.retail.v2alpha.Branch]s under - the specified parent - [Catalog][google.cloud.retail.v2alpha.Catalog]. + r"""Lists all instances of + [Branch][google.cloud.retail.v2alpha.Branch] under the specified + parent [Catalog][google.cloud.retail.v2alpha.Catalog]. .. code-block:: python @@ -439,8 +439,8 @@ async def sample_get_branch(): Returns: google.cloud.retail_v2alpha.types.Branch: - A data branch that stores - [Product][google.cloud.retail.v2alpha.Product]s. + A data branch that stores all instances of + [Product][google.cloud.retail.v2alpha.Product]s. """ # Create or coerce a protobuf request object. diff --git a/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/branch_service/client.py b/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/branch_service/client.py index 1282ec03d8ae..b21b2b52e906 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/branch_service/client.py +++ b/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/branch_service/client.py @@ -744,9 +744,9 @@ def list_branches( timeout: Union[float, object] = gapic_v1.method.DEFAULT, metadata: Sequence[Tuple[str, str]] = (), ) -> branch_service.ListBranchesResponse: - r"""Lists all [Branch][google.cloud.retail.v2alpha.Branch]s under - the specified parent - [Catalog][google.cloud.retail.v2alpha.Catalog]. + r"""Lists all instances of + [Branch][google.cloud.retail.v2alpha.Branch] under the specified + parent [Catalog][google.cloud.retail.v2alpha.Catalog]. .. code-block:: python @@ -903,8 +903,8 @@ def sample_get_branch(): Returns: google.cloud.retail_v2alpha.types.Branch: - A data branch that stores - [Product][google.cloud.retail.v2alpha.Product]s. + A data branch that stores all instances of + [Product][google.cloud.retail.v2alpha.Product]s. """ # Create or coerce a protobuf request object. diff --git a/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/branch_service/transports/grpc.py b/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/branch_service/transports/grpc.py index a06bb90958a2..ba62b2210f91 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/branch_service/transports/grpc.py +++ b/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/branch_service/transports/grpc.py @@ -250,9 +250,9 @@ def list_branches( ]: r"""Return a callable for the list branches method over gRPC. - Lists all [Branch][google.cloud.retail.v2alpha.Branch]s under - the specified parent - [Catalog][google.cloud.retail.v2alpha.Catalog]. + Lists all instances of + [Branch][google.cloud.retail.v2alpha.Branch] under the specified + parent [Catalog][google.cloud.retail.v2alpha.Catalog]. Returns: Callable[[~.ListBranchesRequest], diff --git a/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/branch_service/transports/grpc_asyncio.py b/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/branch_service/transports/grpc_asyncio.py index 50d882760b5f..2d1891f2b751 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/branch_service/transports/grpc_asyncio.py +++ b/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/branch_service/transports/grpc_asyncio.py @@ -255,9 +255,9 @@ def list_branches( ]: r"""Return a callable for the list branches method over gRPC. - Lists all [Branch][google.cloud.retail.v2alpha.Branch]s under - the specified parent - [Catalog][google.cloud.retail.v2alpha.Catalog]. + Lists all instances of + [Branch][google.cloud.retail.v2alpha.Branch] under the specified + parent [Catalog][google.cloud.retail.v2alpha.Catalog]. Returns: Callable[[~.ListBranchesRequest], diff --git a/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/branch_service/transports/rest.py b/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/branch_service/transports/rest.py index d5989f6296d4..2c0376fd3259 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/branch_service/transports/rest.py +++ b/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/branch_service/transports/rest.py @@ -318,7 +318,7 @@ def __call__( Returns: ~.branch.Branch: - A data branch that stores + A data branch that stores all instances of [Product][google.cloud.retail.v2alpha.Product]s. """ diff --git a/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/generative_question_service/__init__.py b/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/generative_question_service/__init__.py new file mode 100644 index 000000000000..f9196ca8080a --- /dev/null +++ b/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/generative_question_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from .async_client import GenerativeQuestionServiceAsyncClient +from .client import GenerativeQuestionServiceClient + +__all__ = ( + "GenerativeQuestionServiceClient", + "GenerativeQuestionServiceAsyncClient", +) diff --git a/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/generative_question_service/async_client.py b/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/generative_question_service/async_client.py new file mode 100644 index 000000000000..52173635118b --- /dev/null +++ b/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/generative_question_service/async_client.py @@ -0,0 +1,1060 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import re +from typing import ( + Callable, + Dict, + Mapping, + MutableMapping, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, +) + +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.api_core.client_options import ClientOptions +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.cloud.retail_v2alpha import gapic_version as package_version + +try: + OptionalRetry = Union[retries.AsyncRetry, gapic_v1.method._MethodDefault, None] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.AsyncRetry, object, None] # type: ignore + +from google.cloud.location import locations_pb2 # type: ignore +from google.longrunning import operations_pb2 # type: ignore +from google.protobuf import field_mask_pb2 # type: ignore + +from google.cloud.retail_v2alpha.types import ( + generative_question, + generative_question_service, +) + +from .client import GenerativeQuestionServiceClient +from .transports.base import DEFAULT_CLIENT_INFO, GenerativeQuestionServiceTransport +from .transports.grpc_asyncio import GenerativeQuestionServiceGrpcAsyncIOTransport + + +class GenerativeQuestionServiceAsyncClient: + """Service for managing LLM generated questions in search + serving. + """ + + _client: GenerativeQuestionServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = GenerativeQuestionServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = GenerativeQuestionServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + GenerativeQuestionServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = GenerativeQuestionServiceClient._DEFAULT_UNIVERSE + + catalog_path = staticmethod(GenerativeQuestionServiceClient.catalog_path) + parse_catalog_path = staticmethod( + GenerativeQuestionServiceClient.parse_catalog_path + ) + common_billing_account_path = staticmethod( + GenerativeQuestionServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + GenerativeQuestionServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + GenerativeQuestionServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + GenerativeQuestionServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + GenerativeQuestionServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + GenerativeQuestionServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + GenerativeQuestionServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + GenerativeQuestionServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + GenerativeQuestionServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + GenerativeQuestionServiceClient.parse_common_location_path + ) + + @classmethod + def from_service_account_info(cls, info: dict, *args, **kwargs): + """Creates an instance of this client using the provided credentials + info. + + Args: + info (dict): The service account private key info. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + GenerativeQuestionServiceAsyncClient: The constructed client. + """ + return GenerativeQuestionServiceClient.from_service_account_info.__func__(GenerativeQuestionServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + GenerativeQuestionServiceAsyncClient: The constructed client. + """ + return GenerativeQuestionServiceClient.from_service_account_file.__func__(GenerativeQuestionServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return GenerativeQuestionServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> GenerativeQuestionServiceTransport: + """Returns the transport used by the client instance. + + Returns: + GenerativeQuestionServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = GenerativeQuestionServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + GenerativeQuestionServiceTransport, + Callable[..., GenerativeQuestionServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the generative question service async client. + + Args: + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + transport (Optional[Union[str,GenerativeQuestionServiceTransport,Callable[..., GenerativeQuestionServiceTransport]]]): + The transport to use, or a Callable that constructs and returns a new transport to use. + If a Callable is given, it will be called with the same set of initialization + arguments as used in the GenerativeQuestionServiceTransport constructor. + If set to None, a transport is chosen automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): + Custom options for the client. + + 1. The ``api_endpoint`` property can be used to override the + default endpoint provided by the client when ``transport`` is + not explicitly provided. Only if this property is not set and + ``transport`` was not explicitly provided, the endpoint is + determined by the GOOGLE_API_USE_MTLS_ENDPOINT environment + variable, which have one of the following values: + "always" (always use the default mTLS endpoint), "never" (always + use the default regular endpoint) and "auto" (auto-switch to the + default mTLS endpoint if client certificate is present; this is + the default value). + + 2. If the GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide a client certificate for mTLS transport. If + not provided, the default SSL client certificate will be used if + present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not + set, no client certificate will be used. + + 3. The ``universe_domain`` property can be used to override the + default "googleapis.com" universe. Note that ``api_endpoint`` + property still takes precedence; and ``universe_domain`` is + currently not supported for mTLS. + + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + + Raises: + google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport + creation failed for any reason. + """ + self._client = GenerativeQuestionServiceClient( + credentials=credentials, + transport=transport, + client_options=client_options, + client_info=client_info, + ) + + async def update_generative_questions_feature_config( + self, + request: Optional[ + Union[ + generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest, + dict, + ] + ] = None, + *, + generative_questions_feature_config: Optional[ + generative_question.GenerativeQuestionsFeatureConfig + ] = None, + update_mask: Optional[field_mask_pb2.FieldMask] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> generative_question.GenerativeQuestionsFeatureConfig: + r"""Manages overal generative question feature state -- + enables toggling feature on and off. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import retail_v2alpha + + async def sample_update_generative_questions_feature_config(): + # Create a client + client = retail_v2alpha.GenerativeQuestionServiceAsyncClient() + + # Initialize request argument(s) + generative_questions_feature_config = retail_v2alpha.GenerativeQuestionsFeatureConfig() + generative_questions_feature_config.catalog = "catalog_value" + + request = retail_v2alpha.UpdateGenerativeQuestionsFeatureConfigRequest( + generative_questions_feature_config=generative_questions_feature_config, + ) + + # Make the request + response = await client.update_generative_questions_feature_config(request=request) + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.retail_v2alpha.types.UpdateGenerativeQuestionsFeatureConfigRequest, dict]]): + The request object. Request for + UpdateGenerativeQuestionsFeatureConfig + method. + generative_questions_feature_config (:class:`google.cloud.retail_v2alpha.types.GenerativeQuestionsFeatureConfig`): + Required. The configuration managing + the feature state. + + This corresponds to the ``generative_questions_feature_config`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + update_mask (:class:`google.protobuf.field_mask_pb2.FieldMask`): + Optional. Indicates which fields in the provided + [GenerativeQuestionsFeatureConfig][google.cloud.retail.v2alpha.GenerativeQuestionsFeatureConfig] + to update. If not set or empty, all supported fields are + updated. + + This corresponds to the ``update_mask`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry_async.AsyncRetry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.retail_v2alpha.types.GenerativeQuestionsFeatureConfig: + Configuration for overall generative + question feature state. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([generative_questions_feature_config, update_mask]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance( + request, + generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest, + ): + request = generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if generative_questions_feature_config is not None: + request.generative_questions_feature_config = ( + generative_questions_feature_config + ) + if update_mask is not None: + request.update_mask = update_mask + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.update_generative_questions_feature_config + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + ( + ( + "generative_questions_feature_config.catalog", + request.generative_questions_feature_config.catalog, + ), + ) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def get_generative_questions_feature_config( + self, + request: Optional[ + Union[ + generative_question_service.GetGenerativeQuestionsFeatureConfigRequest, + dict, + ] + ] = None, + *, + catalog: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> generative_question.GenerativeQuestionsFeatureConfig: + r"""Manages overal generative question feature state -- + enables toggling feature on and off. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import retail_v2alpha + + async def sample_get_generative_questions_feature_config(): + # Create a client + client = retail_v2alpha.GenerativeQuestionServiceAsyncClient() + + # Initialize request argument(s) + request = retail_v2alpha.GetGenerativeQuestionsFeatureConfigRequest( + catalog="catalog_value", + ) + + # Make the request + response = await client.get_generative_questions_feature_config(request=request) + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.retail_v2alpha.types.GetGenerativeQuestionsFeatureConfigRequest, dict]]): + The request object. Request for + GetGenerativeQuestionsFeatureConfig + method. + catalog (:class:`str`): + Required. Resource name of the parent + catalog. Format: + projects/{project}/locations/{location}/catalogs/{catalog} + + This corresponds to the ``catalog`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry_async.AsyncRetry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.retail_v2alpha.types.GenerativeQuestionsFeatureConfig: + Configuration for overall generative + question feature state. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([catalog]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance( + request, + generative_question_service.GetGenerativeQuestionsFeatureConfigRequest, + ): + request = ( + generative_question_service.GetGenerativeQuestionsFeatureConfigRequest( + request + ) + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if catalog is not None: + request.catalog = catalog + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.get_generative_questions_feature_config + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("catalog", request.catalog),)), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def list_generative_question_configs( + self, + request: Optional[ + Union[ + generative_question_service.ListGenerativeQuestionConfigsRequest, dict + ] + ] = None, + *, + parent: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> generative_question_service.ListGenerativeQuestionConfigsResponse: + r"""Returns all questions for a given catalog. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import retail_v2alpha + + async def sample_list_generative_question_configs(): + # Create a client + client = retail_v2alpha.GenerativeQuestionServiceAsyncClient() + + # Initialize request argument(s) + request = retail_v2alpha.ListGenerativeQuestionConfigsRequest( + parent="parent_value", + ) + + # Make the request + response = await client.list_generative_question_configs(request=request) + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.retail_v2alpha.types.ListGenerativeQuestionConfigsRequest, dict]]): + The request object. Request for ListQuestions method. + parent (:class:`str`): + Required. Resource name of the parent + catalog. Format: + projects/{project}/locations/{location}/catalogs/{catalog} + + This corresponds to the ``parent`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry_async.AsyncRetry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.retail_v2alpha.types.ListGenerativeQuestionConfigsResponse: + Response for ListQuestions method. + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([parent]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance( + request, generative_question_service.ListGenerativeQuestionConfigsRequest + ): + request = generative_question_service.ListGenerativeQuestionConfigsRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if parent is not None: + request.parent = parent + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.list_generative_question_configs + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def update_generative_question_config( + self, + request: Optional[ + Union[ + generative_question_service.UpdateGenerativeQuestionConfigRequest, dict + ] + ] = None, + *, + generative_question_config: Optional[ + generative_question.GenerativeQuestionConfig + ] = None, + update_mask: Optional[field_mask_pb2.FieldMask] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> generative_question.GenerativeQuestionConfig: + r"""Allows management of individual questions. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import retail_v2alpha + + async def sample_update_generative_question_config(): + # Create a client + client = retail_v2alpha.GenerativeQuestionServiceAsyncClient() + + # Initialize request argument(s) + generative_question_config = retail_v2alpha.GenerativeQuestionConfig() + generative_question_config.catalog = "catalog_value" + generative_question_config.facet = "facet_value" + + request = retail_v2alpha.UpdateGenerativeQuestionConfigRequest( + generative_question_config=generative_question_config, + ) + + # Make the request + response = await client.update_generative_question_config(request=request) + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.retail_v2alpha.types.UpdateGenerativeQuestionConfigRequest, dict]]): + The request object. Request for + UpdateGenerativeQuestionConfig method. + generative_question_config (:class:`google.cloud.retail_v2alpha.types.GenerativeQuestionConfig`): + Required. The question to update. + This corresponds to the ``generative_question_config`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + update_mask (:class:`google.protobuf.field_mask_pb2.FieldMask`): + Optional. Indicates which fields in the provided + [GenerativeQuestionConfig][google.cloud.retail.v2alpha.GenerativeQuestionConfig] + to update. The following are NOT supported: + + - [GenerativeQuestionConfig.frequency][google.cloud.retail.v2alpha.GenerativeQuestionConfig.frequency] + + If not set or empty, all supported fields are updated. + + This corresponds to the ``update_mask`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry_async.AsyncRetry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.retail_v2alpha.types.GenerativeQuestionConfig: + Configuration for a single generated + question. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([generative_question_config, update_mask]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance( + request, generative_question_service.UpdateGenerativeQuestionConfigRequest + ): + request = generative_question_service.UpdateGenerativeQuestionConfigRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if generative_question_config is not None: + request.generative_question_config = generative_question_config + if update_mask is not None: + request.update_mask = update_mask + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.update_generative_question_config + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + ( + ( + "generative_question_config.catalog", + request.generative_question_config.catalog, + ), + ) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def batch_update_generative_question_configs( + self, + request: Optional[ + Union[ + generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest, + dict, + ] + ] = None, + *, + parent: Optional[str] = None, + requests: Optional[ + MutableSequence[ + generative_question_service.UpdateGenerativeQuestionConfigRequest + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse: + r"""Allows management of multiple questions. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import retail_v2alpha + + async def sample_batch_update_generative_question_configs(): + # Create a client + client = retail_v2alpha.GenerativeQuestionServiceAsyncClient() + + # Initialize request argument(s) + requests = retail_v2alpha.UpdateGenerativeQuestionConfigRequest() + requests.generative_question_config.catalog = "catalog_value" + requests.generative_question_config.facet = "facet_value" + + request = retail_v2alpha.BatchUpdateGenerativeQuestionConfigsRequest( + requests=requests, + ) + + # Make the request + response = await client.batch_update_generative_question_configs(request=request) + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.retail_v2alpha.types.BatchUpdateGenerativeQuestionConfigsRequest, dict]]): + The request object. Request for + BatchUpdateGenerativeQuestionConfig + method. + parent (:class:`str`): + Optional. Resource name of the parent + catalog. Format: + projects/{project}/locations/{location}/catalogs/{catalog} + + This corresponds to the ``parent`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + requests (:class:`MutableSequence[google.cloud.retail_v2alpha.types.UpdateGenerativeQuestionConfigRequest]`): + Required. The updates question + configs. + + This corresponds to the ``requests`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry_async.AsyncRetry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.retail_v2alpha.types.BatchUpdateGenerativeQuestionConfigsResponse: + Aggregated response for + UpdateGenerativeQuestionConfig method. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([parent, requests]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance( + request, + generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest, + ): + request = ( + generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest( + request + ) + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if parent is not None: + request.parent = parent + if requests: + request.requests.extend(requests) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.batch_update_generative_question_configs + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def list_operations( + self, + request: Optional[operations_pb2.ListOperationsRequest] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operations_pb2.ListOperationsResponse: + r"""Lists operations that match the specified filter in the request. + + Args: + request (:class:`~.operations_pb2.ListOperationsRequest`): + The request object. Request message for + `ListOperations` method. + retry (google.api_core.retry_async.AsyncRetry): Designation of what errors, + if any, should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + Returns: + ~.operations_pb2.ListOperationsResponse: + Response message for ``ListOperations`` method. + """ + # Create or coerce a protobuf request object. + # The request isn't a proto-plus wrapped type, + # so it must be constructed via keyword expansion. + if isinstance(request, dict): + request = operations_pb2.ListOperationsRequest(**request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method_async.wrap_method( + self._client._transport.list_operations, + default_timeout=None, + client_info=DEFAULT_CLIENT_INFO, + ) + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def get_operation( + self, + request: Optional[operations_pb2.GetOperationRequest] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operations_pb2.Operation: + r"""Gets the latest state of a long-running operation. + + Args: + request (:class:`~.operations_pb2.GetOperationRequest`): + The request object. Request message for + `GetOperation` method. + retry (google.api_core.retry_async.AsyncRetry): Designation of what errors, + if any, should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + Returns: + ~.operations_pb2.Operation: + An ``Operation`` object. + """ + # Create or coerce a protobuf request object. + # The request isn't a proto-plus wrapped type, + # so it must be constructed via keyword expansion. + if isinstance(request, dict): + request = operations_pb2.GetOperationRequest(**request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method_async.wrap_method( + self._client._transport.get_operation, + default_timeout=None, + client_info=DEFAULT_CLIENT_INFO, + ) + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "GenerativeQuestionServiceAsyncClient": + return self + + async def __aexit__(self, exc_type, exc, tb): + await self.transport.close() + + +DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=package_version.__version__ +) + + +__all__ = ("GenerativeQuestionServiceAsyncClient",) diff --git a/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/generative_question_service/client.py b/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/generative_question_service/client.py new file mode 100644 index 000000000000..b37acbe562f6 --- /dev/null +++ b/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/generative_question_service/client.py @@ -0,0 +1,1480 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Callable, + Dict, + Mapping, + MutableMapping, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.cloud.retail_v2alpha import gapic_version as package_version + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault, None] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object, None] # type: ignore + +from google.cloud.location import locations_pb2 # type: ignore +from google.longrunning import operations_pb2 # type: ignore +from google.protobuf import field_mask_pb2 # type: ignore + +from google.cloud.retail_v2alpha.types import ( + generative_question, + generative_question_service, +) + +from .transports.base import DEFAULT_CLIENT_INFO, GenerativeQuestionServiceTransport +from .transports.grpc import GenerativeQuestionServiceGrpcTransport +from .transports.grpc_asyncio import GenerativeQuestionServiceGrpcAsyncIOTransport +from .transports.rest import GenerativeQuestionServiceRestTransport + + +class GenerativeQuestionServiceClientMeta(type): + """Metaclass for the GenerativeQuestionService client. + + This provides class-level methods for building and retrieving + support objects (e.g. transport) without polluting the client instance + objects. + """ + + _transport_registry = ( + OrderedDict() + ) # type: Dict[str, Type[GenerativeQuestionServiceTransport]] + _transport_registry["grpc"] = GenerativeQuestionServiceGrpcTransport + _transport_registry["grpc_asyncio"] = GenerativeQuestionServiceGrpcAsyncIOTransport + _transport_registry["rest"] = GenerativeQuestionServiceRestTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[GenerativeQuestionServiceTransport]: + """Returns an appropriate transport class. + + Args: + label: The name of the desired transport. If none is + provided, then the first transport in the registry is used. + + Returns: + The transport class to use. + """ + # If a specific transport is requested, return that one. + if label: + return cls._transport_registry[label] + + # No transport is requested; return the default (that is, the first one + # in the dictionary). + return next(iter(cls._transport_registry.values())) + + +class GenerativeQuestionServiceClient(metaclass=GenerativeQuestionServiceClientMeta): + """Service for managing LLM generated questions in search + serving. + """ + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "retail.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "retail.{UNIVERSE_DOMAIN}" + _DEFAULT_UNIVERSE = "googleapis.com" + + @classmethod + def from_service_account_info(cls, info: dict, *args, **kwargs): + """Creates an instance of this client using the provided credentials + info. + + Args: + info (dict): The service account private key info. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + GenerativeQuestionServiceClient: The constructed client. + """ + credentials = service_account.Credentials.from_service_account_info(info) + kwargs["credentials"] = credentials + return cls(*args, **kwargs) + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + GenerativeQuestionServiceClient: The constructed client. + """ + credentials = service_account.Credentials.from_service_account_file(filename) + kwargs["credentials"] = credentials + return cls(*args, **kwargs) + + from_service_account_json = from_service_account_file + + @property + def transport(self) -> GenerativeQuestionServiceTransport: + """Returns the transport used by the client instance. + + Returns: + GenerativeQuestionServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def catalog_path( + project: str, + location: str, + catalog: str, + ) -> str: + """Returns a fully-qualified catalog string.""" + return "projects/{project}/locations/{location}/catalogs/{catalog}".format( + project=project, + location=location, + catalog=catalog, + ) + + @staticmethod + def parse_catalog_path(path: str) -> Dict[str, str]: + """Parses a catalog path into its component segments.""" + m = re.match( + r"^projects/(?P.+?)/locations/(?P.+?)/catalogs/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def common_billing_account_path( + billing_account: str, + ) -> str: + """Returns a fully-qualified billing_account string.""" + return "billingAccounts/{billing_account}".format( + billing_account=billing_account, + ) + + @staticmethod + def parse_common_billing_account_path(path: str) -> Dict[str, str]: + """Parse a billing_account path into its component segments.""" + m = re.match(r"^billingAccounts/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_folder_path( + folder: str, + ) -> str: + """Returns a fully-qualified folder string.""" + return "folders/{folder}".format( + folder=folder, + ) + + @staticmethod + def parse_common_folder_path(path: str) -> Dict[str, str]: + """Parse a folder path into its component segments.""" + m = re.match(r"^folders/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_organization_path( + organization: str, + ) -> str: + """Returns a fully-qualified organization string.""" + return "organizations/{organization}".format( + organization=organization, + ) + + @staticmethod + def parse_common_organization_path(path: str) -> Dict[str, str]: + """Parse a organization path into its component segments.""" + m = re.match(r"^organizations/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_project_path( + project: str, + ) -> str: + """Returns a fully-qualified project string.""" + return "projects/{project}".format( + project=project, + ) + + @staticmethod + def parse_common_project_path(path: str) -> Dict[str, str]: + """Parse a project path into its component segments.""" + m = re.match(r"^projects/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_location_path( + project: str, + location: str, + ) -> str: + """Returns a fully-qualified location string.""" + return "projects/{project}/locations/{location}".format( + project=project, + location=location, + ) + + @staticmethod + def parse_common_location_path(path: str) -> Dict[str, str]: + """Parse a location path into its component segments.""" + m = re.match(r"^projects/(?P.+?)/locations/(?P.+?)$", path) + return m.groupdict() if m else {} + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[client_options_lib.ClientOptions] = None + ): + """Deprecated. Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + + warnings.warn( + "get_mtls_endpoint_and_cert_source is deprecated. Use the api_endpoint property instead.", + DeprecationWarning, + ) + if client_options is None: + client_options = client_options_lib.ClientOptions() + use_client_cert = os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") + use_mtls_endpoint = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_client_cert not in ("true", "false"): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + if use_mtls_endpoint not in ("auto", "never", "always"): + raise MutualTLSChannelError( + "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`" + ) + + # Figure out the client cert source to use. + client_cert_source = None + if use_client_cert == "true": + if client_options.client_cert_source: + client_cert_source = client_options.client_cert_source + elif mtls.has_default_client_cert_source(): + client_cert_source = mtls.default_client_cert_source() + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + elif use_mtls_endpoint == "always" or ( + use_mtls_endpoint == "auto" and client_cert_source + ): + api_endpoint = cls.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = cls.DEFAULT_ENDPOINT + + return api_endpoint, client_cert_source + + @staticmethod + def _read_environment_variables(): + """Returns the environment variables used by the client. + + Returns: + Tuple[bool, str, str]: returns the GOOGLE_API_USE_CLIENT_CERTIFICATE, + GOOGLE_API_USE_MTLS_ENDPOINT, and GOOGLE_CLOUD_UNIVERSE_DOMAIN environment variables. + + Raises: + ValueError: If GOOGLE_API_USE_CLIENT_CERTIFICATE is not + any of ["true", "false"]. + google.auth.exceptions.MutualTLSChannelError: If GOOGLE_API_USE_MTLS_ENDPOINT + is not any of ["auto", "never", "always"]. + """ + use_client_cert = os.getenv( + "GOOGLE_API_USE_CLIENT_CERTIFICATE", "false" + ).lower() + use_mtls_endpoint = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto").lower() + universe_domain_env = os.getenv("GOOGLE_CLOUD_UNIVERSE_DOMAIN") + if use_client_cert not in ("true", "false"): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + if use_mtls_endpoint not in ("auto", "never", "always"): + raise MutualTLSChannelError( + "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`" + ) + return use_client_cert == "true", use_mtls_endpoint, universe_domain_env + + @staticmethod + def _get_client_cert_source(provided_cert_source, use_cert_flag): + """Return the client cert source to be used by the client. + + Args: + provided_cert_source (bytes): The client certificate source provided. + use_cert_flag (bool): A flag indicating whether to use the client certificate. + + Returns: + bytes or None: The client cert source to be used by the client. + """ + client_cert_source = None + if use_cert_flag: + if provided_cert_source: + client_cert_source = provided_cert_source + elif mtls.has_default_client_cert_source(): + client_cert_source = mtls.default_client_cert_source() + return client_cert_source + + @staticmethod + def _get_api_endpoint( + api_override, client_cert_source, universe_domain, use_mtls_endpoint + ): + """Return the API endpoint used by the client. + + Args: + api_override (str): The API endpoint override. If specified, this is always + the return value of this function and the other arguments are not used. + client_cert_source (bytes): The client certificate source used by the client. + universe_domain (str): The universe domain used by the client. + use_mtls_endpoint (str): How to use the mTLS endpoint, which depends also on the other parameters. + Possible values are "always", "auto", or "never". + + Returns: + str: The API endpoint to be used by the client. + """ + if api_override is not None: + api_endpoint = api_override + elif use_mtls_endpoint == "always" or ( + use_mtls_endpoint == "auto" and client_cert_source + ): + _default_universe = GenerativeQuestionServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = GenerativeQuestionServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + GenerativeQuestionServiceClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=universe_domain + ) + ) + return api_endpoint + + @staticmethod + def _get_universe_domain( + client_universe_domain: Optional[str], universe_domain_env: Optional[str] + ) -> str: + """Return the universe domain used by the client. + + Args: + client_universe_domain (Optional[str]): The universe domain configured via the client options. + universe_domain_env (Optional[str]): The universe domain configured via the "GOOGLE_CLOUD_UNIVERSE_DOMAIN" environment variable. + + Returns: + str: The universe domain to be used by the client. + + Raises: + ValueError: If the universe domain is an empty string. + """ + universe_domain = GenerativeQuestionServiceClient._DEFAULT_UNIVERSE + if client_universe_domain is not None: + universe_domain = client_universe_domain + elif universe_domain_env is not None: + universe_domain = universe_domain_env + if len(universe_domain.strip()) == 0: + raise ValueError("Universe Domain cannot be an empty string.") + return universe_domain + + @staticmethod + def _compare_universes( + client_universe: str, credentials: ga_credentials.Credentials + ) -> bool: + """Returns True iff the universe domains used by the client and credentials match. + + Args: + client_universe (str): The universe domain configured via the client options. + credentials (ga_credentials.Credentials): The credentials being used in the client. + + Returns: + bool: True iff client_universe matches the universe in credentials. + + Raises: + ValueError: when client_universe does not match the universe in credentials. + """ + + default_universe = GenerativeQuestionServiceClient._DEFAULT_UNIVERSE + credentials_universe = getattr(credentials, "universe_domain", default_universe) + + if client_universe != credentials_universe: + raise ValueError( + "The configured universe domain " + f"({client_universe}) does not match the universe domain " + f"found in the credentials ({credentials_universe}). " + "If you haven't configured the universe domain explicitly, " + f"`{default_universe}` is the default." + ) + return True + + def _validate_universe_domain(self): + """Validates client's and credentials' universe domains are consistent. + + Returns: + bool: True iff the configured universe domain is valid. + + Raises: + ValueError: If the configured universe domain is not valid. + """ + self._is_universe_domain_valid = ( + self._is_universe_domain_valid + or GenerativeQuestionServiceClient._compare_universes( + self.universe_domain, self.transport._credentials + ) + ) + return self._is_universe_domain_valid + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used by the client instance. + """ + return self._universe_domain + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + GenerativeQuestionServiceTransport, + Callable[..., GenerativeQuestionServiceTransport], + ] + ] = None, + client_options: Optional[Union[client_options_lib.ClientOptions, dict]] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the generative question service client. + + Args: + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + transport (Optional[Union[str,GenerativeQuestionServiceTransport,Callable[..., GenerativeQuestionServiceTransport]]]): + The transport to use, or a Callable that constructs and returns a new transport. + If a Callable is given, it will be called with the same set of initialization + arguments as used in the GenerativeQuestionServiceTransport constructor. + If set to None, a transport is chosen automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): + Custom options for the client. + + 1. The ``api_endpoint`` property can be used to override the + default endpoint provided by the client when ``transport`` is + not explicitly provided. Only if this property is not set and + ``transport`` was not explicitly provided, the endpoint is + determined by the GOOGLE_API_USE_MTLS_ENDPOINT environment + variable, which have one of the following values: + "always" (always use the default mTLS endpoint), "never" (always + use the default regular endpoint) and "auto" (auto-switch to the + default mTLS endpoint if client certificate is present; this is + the default value). + + 2. If the GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide a client certificate for mTLS transport. If + not provided, the default SSL client certificate will be used if + present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not + set, no client certificate will be used. + + 3. The ``universe_domain`` property can be used to override the + default "googleapis.com" universe. Note that the ``api_endpoint`` + property still takes precedence; and ``universe_domain`` is + currently not supported for mTLS. + + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + """ + self._client_options = client_options + if isinstance(self._client_options, dict): + self._client_options = client_options_lib.from_dict(self._client_options) + if self._client_options is None: + self._client_options = client_options_lib.ClientOptions() + self._client_options = cast( + client_options_lib.ClientOptions, self._client_options + ) + + universe_domain_opt = getattr(self._client_options, "universe_domain", None) + + ( + self._use_client_cert, + self._use_mtls_endpoint, + self._universe_domain_env, + ) = GenerativeQuestionServiceClient._read_environment_variables() + self._client_cert_source = ( + GenerativeQuestionServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = GenerativeQuestionServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + api_key_value = getattr(self._client_options, "api_key", None) + if api_key_value and credentials: + raise ValueError( + "client_options.api_key and credentials are mutually exclusive" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + transport_provided = isinstance(transport, GenerativeQuestionServiceTransport) + if transport_provided: + # transport is a GenerativeQuestionServiceTransport instance. + if credentials or self._client_options.credentials_file or api_key_value: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if self._client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = cast(GenerativeQuestionServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or GenerativeQuestionServiceClient._get_api_endpoint( + self._client_options.api_endpoint, + self._client_cert_source, + self._universe_domain, + self._use_mtls_endpoint, + ) + ) + + if not transport_provided: + import google.auth._default # type: ignore + + if api_key_value and hasattr( + google.auth._default, "get_api_key_credentials" + ): + credentials = google.auth._default.get_api_key_credentials( + api_key_value + ) + + transport_init: Union[ + Type[GenerativeQuestionServiceTransport], + Callable[..., GenerativeQuestionServiceTransport], + ] = ( + GenerativeQuestionServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast(Callable[..., GenerativeQuestionServiceTransport], transport) + ) + # initialize with the provided callable or the passed in class + self._transport = transport_init( + credentials=credentials, + credentials_file=self._client_options.credentials_file, + host=self._api_endpoint, + scopes=self._client_options.scopes, + client_cert_source_for_mtls=self._client_cert_source, + quota_project_id=self._client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + api_audience=self._client_options.api_audience, + ) + + def update_generative_questions_feature_config( + self, + request: Optional[ + Union[ + generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest, + dict, + ] + ] = None, + *, + generative_questions_feature_config: Optional[ + generative_question.GenerativeQuestionsFeatureConfig + ] = None, + update_mask: Optional[field_mask_pb2.FieldMask] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> generative_question.GenerativeQuestionsFeatureConfig: + r"""Manages overal generative question feature state -- + enables toggling feature on and off. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import retail_v2alpha + + def sample_update_generative_questions_feature_config(): + # Create a client + client = retail_v2alpha.GenerativeQuestionServiceClient() + + # Initialize request argument(s) + generative_questions_feature_config = retail_v2alpha.GenerativeQuestionsFeatureConfig() + generative_questions_feature_config.catalog = "catalog_value" + + request = retail_v2alpha.UpdateGenerativeQuestionsFeatureConfigRequest( + generative_questions_feature_config=generative_questions_feature_config, + ) + + # Make the request + response = client.update_generative_questions_feature_config(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.retail_v2alpha.types.UpdateGenerativeQuestionsFeatureConfigRequest, dict]): + The request object. Request for + UpdateGenerativeQuestionsFeatureConfig + method. + generative_questions_feature_config (google.cloud.retail_v2alpha.types.GenerativeQuestionsFeatureConfig): + Required. The configuration managing + the feature state. + + This corresponds to the ``generative_questions_feature_config`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + update_mask (google.protobuf.field_mask_pb2.FieldMask): + Optional. Indicates which fields in the provided + [GenerativeQuestionsFeatureConfig][google.cloud.retail.v2alpha.GenerativeQuestionsFeatureConfig] + to update. If not set or empty, all supported fields are + updated. + + This corresponds to the ``update_mask`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.retail_v2alpha.types.GenerativeQuestionsFeatureConfig: + Configuration for overall generative + question feature state. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([generative_questions_feature_config, update_mask]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance( + request, + generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest, + ): + request = generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if generative_questions_feature_config is not None: + request.generative_questions_feature_config = ( + generative_questions_feature_config + ) + if update_mask is not None: + request.update_mask = update_mask + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.update_generative_questions_feature_config + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + ( + ( + "generative_questions_feature_config.catalog", + request.generative_questions_feature_config.catalog, + ), + ) + ), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + def get_generative_questions_feature_config( + self, + request: Optional[ + Union[ + generative_question_service.GetGenerativeQuestionsFeatureConfigRequest, + dict, + ] + ] = None, + *, + catalog: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> generative_question.GenerativeQuestionsFeatureConfig: + r"""Manages overal generative question feature state -- + enables toggling feature on and off. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import retail_v2alpha + + def sample_get_generative_questions_feature_config(): + # Create a client + client = retail_v2alpha.GenerativeQuestionServiceClient() + + # Initialize request argument(s) + request = retail_v2alpha.GetGenerativeQuestionsFeatureConfigRequest( + catalog="catalog_value", + ) + + # Make the request + response = client.get_generative_questions_feature_config(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.retail_v2alpha.types.GetGenerativeQuestionsFeatureConfigRequest, dict]): + The request object. Request for + GetGenerativeQuestionsFeatureConfig + method. + catalog (str): + Required. Resource name of the parent + catalog. Format: + projects/{project}/locations/{location}/catalogs/{catalog} + + This corresponds to the ``catalog`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.retail_v2alpha.types.GenerativeQuestionsFeatureConfig: + Configuration for overall generative + question feature state. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([catalog]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance( + request, + generative_question_service.GetGenerativeQuestionsFeatureConfigRequest, + ): + request = ( + generative_question_service.GetGenerativeQuestionsFeatureConfigRequest( + request + ) + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if catalog is not None: + request.catalog = catalog + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.get_generative_questions_feature_config + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("catalog", request.catalog),)), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + def list_generative_question_configs( + self, + request: Optional[ + Union[ + generative_question_service.ListGenerativeQuestionConfigsRequest, dict + ] + ] = None, + *, + parent: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> generative_question_service.ListGenerativeQuestionConfigsResponse: + r"""Returns all questions for a given catalog. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import retail_v2alpha + + def sample_list_generative_question_configs(): + # Create a client + client = retail_v2alpha.GenerativeQuestionServiceClient() + + # Initialize request argument(s) + request = retail_v2alpha.ListGenerativeQuestionConfigsRequest( + parent="parent_value", + ) + + # Make the request + response = client.list_generative_question_configs(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.retail_v2alpha.types.ListGenerativeQuestionConfigsRequest, dict]): + The request object. Request for ListQuestions method. + parent (str): + Required. Resource name of the parent + catalog. Format: + projects/{project}/locations/{location}/catalogs/{catalog} + + This corresponds to the ``parent`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.retail_v2alpha.types.ListGenerativeQuestionConfigsResponse: + Response for ListQuestions method. + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([parent]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance( + request, generative_question_service.ListGenerativeQuestionConfigsRequest + ): + request = generative_question_service.ListGenerativeQuestionConfigsRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if parent is not None: + request.parent = parent + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.list_generative_question_configs + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + def update_generative_question_config( + self, + request: Optional[ + Union[ + generative_question_service.UpdateGenerativeQuestionConfigRequest, dict + ] + ] = None, + *, + generative_question_config: Optional[ + generative_question.GenerativeQuestionConfig + ] = None, + update_mask: Optional[field_mask_pb2.FieldMask] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> generative_question.GenerativeQuestionConfig: + r"""Allows management of individual questions. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import retail_v2alpha + + def sample_update_generative_question_config(): + # Create a client + client = retail_v2alpha.GenerativeQuestionServiceClient() + + # Initialize request argument(s) + generative_question_config = retail_v2alpha.GenerativeQuestionConfig() + generative_question_config.catalog = "catalog_value" + generative_question_config.facet = "facet_value" + + request = retail_v2alpha.UpdateGenerativeQuestionConfigRequest( + generative_question_config=generative_question_config, + ) + + # Make the request + response = client.update_generative_question_config(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.retail_v2alpha.types.UpdateGenerativeQuestionConfigRequest, dict]): + The request object. Request for + UpdateGenerativeQuestionConfig method. + generative_question_config (google.cloud.retail_v2alpha.types.GenerativeQuestionConfig): + Required. The question to update. + This corresponds to the ``generative_question_config`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + update_mask (google.protobuf.field_mask_pb2.FieldMask): + Optional. Indicates which fields in the provided + [GenerativeQuestionConfig][google.cloud.retail.v2alpha.GenerativeQuestionConfig] + to update. The following are NOT supported: + + - [GenerativeQuestionConfig.frequency][google.cloud.retail.v2alpha.GenerativeQuestionConfig.frequency] + + If not set or empty, all supported fields are updated. + + This corresponds to the ``update_mask`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.retail_v2alpha.types.GenerativeQuestionConfig: + Configuration for a single generated + question. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([generative_question_config, update_mask]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance( + request, generative_question_service.UpdateGenerativeQuestionConfigRequest + ): + request = generative_question_service.UpdateGenerativeQuestionConfigRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if generative_question_config is not None: + request.generative_question_config = generative_question_config + if update_mask is not None: + request.update_mask = update_mask + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.update_generative_question_config + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + ( + ( + "generative_question_config.catalog", + request.generative_question_config.catalog, + ), + ) + ), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + def batch_update_generative_question_configs( + self, + request: Optional[ + Union[ + generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest, + dict, + ] + ] = None, + *, + parent: Optional[str] = None, + requests: Optional[ + MutableSequence[ + generative_question_service.UpdateGenerativeQuestionConfigRequest + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse: + r"""Allows management of multiple questions. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import retail_v2alpha + + def sample_batch_update_generative_question_configs(): + # Create a client + client = retail_v2alpha.GenerativeQuestionServiceClient() + + # Initialize request argument(s) + requests = retail_v2alpha.UpdateGenerativeQuestionConfigRequest() + requests.generative_question_config.catalog = "catalog_value" + requests.generative_question_config.facet = "facet_value" + + request = retail_v2alpha.BatchUpdateGenerativeQuestionConfigsRequest( + requests=requests, + ) + + # Make the request + response = client.batch_update_generative_question_configs(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.retail_v2alpha.types.BatchUpdateGenerativeQuestionConfigsRequest, dict]): + The request object. Request for + BatchUpdateGenerativeQuestionConfig + method. + parent (str): + Optional. Resource name of the parent + catalog. Format: + projects/{project}/locations/{location}/catalogs/{catalog} + + This corresponds to the ``parent`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + requests (MutableSequence[google.cloud.retail_v2alpha.types.UpdateGenerativeQuestionConfigRequest]): + Required. The updates question + configs. + + This corresponds to the ``requests`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.retail_v2alpha.types.BatchUpdateGenerativeQuestionConfigsResponse: + Aggregated response for + UpdateGenerativeQuestionConfig method. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([parent, requests]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance( + request, + generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest, + ): + request = ( + generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest( + request + ) + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if parent is not None: + request.parent = parent + if requests is not None: + request.requests = requests + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.batch_update_generative_question_configs + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + def __enter__(self) -> "GenerativeQuestionServiceClient": + return self + + def __exit__(self, type, value, traceback): + """Releases underlying transport's resources. + + .. warning:: + ONLY use as a context manager if the transport is NOT shared + with other clients! Exiting the with block will CLOSE the transport + and may cause errors in other clients! + """ + self.transport.close() + + def list_operations( + self, + request: Optional[operations_pb2.ListOperationsRequest] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operations_pb2.ListOperationsResponse: + r"""Lists operations that match the specified filter in the request. + + Args: + request (:class:`~.operations_pb2.ListOperationsRequest`): + The request object. Request message for + `ListOperations` method. + retry (google.api_core.retry.Retry): Designation of what errors, + if any, should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + Returns: + ~.operations_pb2.ListOperationsResponse: + Response message for ``ListOperations`` method. + """ + # Create or coerce a protobuf request object. + # The request isn't a proto-plus wrapped type, + # so it must be constructed via keyword expansion. + if isinstance(request, dict): + request = operations_pb2.ListOperationsRequest(**request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method.wrap_method( + self._transport.list_operations, + default_timeout=None, + client_info=DEFAULT_CLIENT_INFO, + ) + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + def get_operation( + self, + request: Optional[operations_pb2.GetOperationRequest] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operations_pb2.Operation: + r"""Gets the latest state of a long-running operation. + + Args: + request (:class:`~.operations_pb2.GetOperationRequest`): + The request object. Request message for + `GetOperation` method. + retry (google.api_core.retry.Retry): Designation of what errors, + if any, should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + Returns: + ~.operations_pb2.Operation: + An ``Operation`` object. + """ + # Create or coerce a protobuf request object. + # The request isn't a proto-plus wrapped type, + # so it must be constructed via keyword expansion. + if isinstance(request, dict): + request = operations_pb2.GetOperationRequest(**request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method.wrap_method( + self._transport.get_operation, + default_timeout=None, + client_info=DEFAULT_CLIENT_INFO, + ) + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=package_version.__version__ +) + + +__all__ = ("GenerativeQuestionServiceClient",) diff --git a/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/generative_question_service/transports/__init__.py b/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/generative_question_service/transports/__init__.py new file mode 100644 index 000000000000..9e57f7d430ba --- /dev/null +++ b/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/generative_question_service/transports/__init__.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +from typing import Dict, Type + +from .base import GenerativeQuestionServiceTransport +from .grpc import GenerativeQuestionServiceGrpcTransport +from .grpc_asyncio import GenerativeQuestionServiceGrpcAsyncIOTransport +from .rest import ( + GenerativeQuestionServiceRestInterceptor, + GenerativeQuestionServiceRestTransport, +) + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[GenerativeQuestionServiceTransport]] +_transport_registry["grpc"] = GenerativeQuestionServiceGrpcTransport +_transport_registry["grpc_asyncio"] = GenerativeQuestionServiceGrpcAsyncIOTransport +_transport_registry["rest"] = GenerativeQuestionServiceRestTransport + +__all__ = ( + "GenerativeQuestionServiceTransport", + "GenerativeQuestionServiceGrpcTransport", + "GenerativeQuestionServiceGrpcAsyncIOTransport", + "GenerativeQuestionServiceRestTransport", + "GenerativeQuestionServiceRestInterceptor", +) diff --git a/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/generative_question_service/transports/base.py b/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/generative_question_service/transports/base.py new file mode 100644 index 000000000000..237bc3a91b0c --- /dev/null +++ b/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/generative_question_service/transports/base.py @@ -0,0 +1,262 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import abc +from typing import Awaitable, Callable, Dict, Optional, Sequence, Union + +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.cloud.location import locations_pb2 # type: ignore +from google.longrunning import operations_pb2 # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.cloud.retail_v2alpha import gapic_version as package_version +from google.cloud.retail_v2alpha.types import ( + generative_question, + generative_question_service, +) + +DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=package_version.__version__ +) + + +class GenerativeQuestionServiceTransport(abc.ABC): + """Abstract transport class for GenerativeQuestionService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/cloud-platform",) + + DEFAULT_HOST: str = "retail.googleapis.com" + + def __init__( + self, + *, + host: str = DEFAULT_HOST, + credentials: Optional[ga_credentials.Credentials] = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + quota_project_id: Optional[str] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, + api_audience: Optional[str] = None, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to (default: 'retail.googleapis.com'). + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, **scopes_kwargs, quota_project_id=quota_project_id + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr(service_account.Credentials, "with_always_use_jwt_access") + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.update_generative_questions_feature_config: gapic_v1.method.wrap_method( + self.update_generative_questions_feature_config, + default_timeout=None, + client_info=client_info, + ), + self.get_generative_questions_feature_config: gapic_v1.method.wrap_method( + self.get_generative_questions_feature_config, + default_timeout=None, + client_info=client_info, + ), + self.list_generative_question_configs: gapic_v1.method.wrap_method( + self.list_generative_question_configs, + default_timeout=None, + client_info=client_info, + ), + self.update_generative_question_config: gapic_v1.method.wrap_method( + self.update_generative_question_config, + default_timeout=None, + client_info=client_info, + ), + self.batch_update_generative_question_configs: gapic_v1.method.wrap_method( + self.batch_update_generative_question_configs, + default_timeout=None, + client_info=client_info, + ), + } + + def close(self): + """Closes resources associated with the transport. + + .. warning:: + Only call this method if the transport is NOT shared + with other clients - this may cause errors in other clients! + """ + raise NotImplementedError() + + @property + def update_generative_questions_feature_config( + self, + ) -> Callable[ + [generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest], + Union[ + generative_question.GenerativeQuestionsFeatureConfig, + Awaitable[generative_question.GenerativeQuestionsFeatureConfig], + ], + ]: + raise NotImplementedError() + + @property + def get_generative_questions_feature_config( + self, + ) -> Callable[ + [generative_question_service.GetGenerativeQuestionsFeatureConfigRequest], + Union[ + generative_question.GenerativeQuestionsFeatureConfig, + Awaitable[generative_question.GenerativeQuestionsFeatureConfig], + ], + ]: + raise NotImplementedError() + + @property + def list_generative_question_configs( + self, + ) -> Callable[ + [generative_question_service.ListGenerativeQuestionConfigsRequest], + Union[ + generative_question_service.ListGenerativeQuestionConfigsResponse, + Awaitable[ + generative_question_service.ListGenerativeQuestionConfigsResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def update_generative_question_config( + self, + ) -> Callable[ + [generative_question_service.UpdateGenerativeQuestionConfigRequest], + Union[ + generative_question.GenerativeQuestionConfig, + Awaitable[generative_question.GenerativeQuestionConfig], + ], + ]: + raise NotImplementedError() + + @property + def batch_update_generative_question_configs( + self, + ) -> Callable[ + [generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest], + Union[ + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse, + Awaitable[ + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def list_operations( + self, + ) -> Callable[ + [operations_pb2.ListOperationsRequest], + Union[ + operations_pb2.ListOperationsResponse, + Awaitable[operations_pb2.ListOperationsResponse], + ], + ]: + raise NotImplementedError() + + @property + def get_operation( + self, + ) -> Callable[ + [operations_pb2.GetOperationRequest], + Union[operations_pb2.Operation, Awaitable[operations_pb2.Operation]], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("GenerativeQuestionServiceTransport",) diff --git a/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/generative_question_service/transports/grpc.py b/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/generative_question_service/transports/grpc.py new file mode 100644 index 000000000000..7776c6e3c4b3 --- /dev/null +++ b/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/generative_question_service/transports/grpc.py @@ -0,0 +1,449 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from typing import Callable, Dict, Optional, Sequence, Tuple, Union +import warnings + +from google.api_core import gapic_v1, grpc_helpers +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.cloud.location import locations_pb2 # type: ignore +from google.longrunning import operations_pb2 # type: ignore +import grpc # type: ignore + +from google.cloud.retail_v2alpha.types import ( + generative_question, + generative_question_service, +) + +from .base import DEFAULT_CLIENT_INFO, GenerativeQuestionServiceTransport + + +class GenerativeQuestionServiceGrpcTransport(GenerativeQuestionServiceTransport): + """gRPC backend transport for GenerativeQuestionService. + + Service for managing LLM generated questions in search + serving. + + This class defines the same methods as the primary client, so the + primary client can load the underlying transport implementation + and call it. + + It sends protocol buffers over the wire using gRPC (which is built on + top of HTTP/2); the ``grpcio`` package must be installed. + """ + + _stubs: Dict[str, Callable] + + def __init__( + self, + *, + host: str = "retail.googleapis.com", + credentials: Optional[ga_credentials.Credentials] = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + channel: Optional[Union[grpc.Channel, Callable[..., grpc.Channel]]] = None, + api_mtls_endpoint: Optional[str] = None, + client_cert_source: Optional[Callable[[], Tuple[bytes, bytes]]] = None, + ssl_channel_credentials: Optional[grpc.ChannelCredentials] = None, + client_cert_source_for_mtls: Optional[Callable[[], Tuple[bytes, bytes]]] = None, + quota_project_id: Optional[str] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, + api_audience: Optional[str] = None, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to (default: 'retail.googleapis.com'). + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if a ``channel`` instance is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if a ``channel`` instance is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if a ``channel`` instance is provided. + channel (Optional[Union[grpc.Channel, Callable[..., grpc.Channel]]]): + A ``Channel`` instance through which to make calls, or a Callable + that constructs and returns one. If set to None, ``self.create_channel`` + is used to create the channel. If a Callable is given, it will be called + with the same arguments as used in ``self.create_channel``. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if a ``channel`` instance is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if a ``channel`` instance or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn("client_cert_source is deprecated", DeprecationWarning) + + if isinstance(channel, grpc.Channel): + # Ignore credentials if a channel was passed. + credentials = None + self._ignore_credentials = True + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + else: + self._ssl_channel_credentials = SslCredentials().ssl_credentials + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + api_audience=api_audience, + ) + + if not self._grpc_channel: + # initialize with the provided callable or the default channel + channel_init = channel or type(self).create_channel + self._grpc_channel = channel_init( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "retail.googleapis.com", + credentials: Optional[ga_credentials.Credentials] = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + quota_project_id: Optional[str] = None, + **kwargs, + ) -> grpc.Channel: + """Create and return a gRPC channel object. + Args: + host (Optional[str]): The host for the channel to use. + credentials (Optional[~.Credentials]): The + authorization credentials to attach to requests. These + credentials identify this application to the service. If + none are specified, the client will attempt to ascertain + the credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def update_generative_questions_feature_config( + self, + ) -> Callable[ + [generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest], + generative_question.GenerativeQuestionsFeatureConfig, + ]: + r"""Return a callable for the update generative questions + feature config method over gRPC. + + Manages overal generative question feature state -- + enables toggling feature on and off. + + Returns: + Callable[[~.UpdateGenerativeQuestionsFeatureConfigRequest], + ~.GenerativeQuestionsFeatureConfig]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "update_generative_questions_feature_config" not in self._stubs: + self._stubs[ + "update_generative_questions_feature_config" + ] = self.grpc_channel.unary_unary( + "/google.cloud.retail.v2alpha.GenerativeQuestionService/UpdateGenerativeQuestionsFeatureConfig", + request_serializer=generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest.serialize, + response_deserializer=generative_question.GenerativeQuestionsFeatureConfig.deserialize, + ) + return self._stubs["update_generative_questions_feature_config"] + + @property + def get_generative_questions_feature_config( + self, + ) -> Callable[ + [generative_question_service.GetGenerativeQuestionsFeatureConfigRequest], + generative_question.GenerativeQuestionsFeatureConfig, + ]: + r"""Return a callable for the get generative questions + feature config method over gRPC. + + Manages overal generative question feature state -- + enables toggling feature on and off. + + Returns: + Callable[[~.GetGenerativeQuestionsFeatureConfigRequest], + ~.GenerativeQuestionsFeatureConfig]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "get_generative_questions_feature_config" not in self._stubs: + self._stubs[ + "get_generative_questions_feature_config" + ] = self.grpc_channel.unary_unary( + "/google.cloud.retail.v2alpha.GenerativeQuestionService/GetGenerativeQuestionsFeatureConfig", + request_serializer=generative_question_service.GetGenerativeQuestionsFeatureConfigRequest.serialize, + response_deserializer=generative_question.GenerativeQuestionsFeatureConfig.deserialize, + ) + return self._stubs["get_generative_questions_feature_config"] + + @property + def list_generative_question_configs( + self, + ) -> Callable[ + [generative_question_service.ListGenerativeQuestionConfigsRequest], + generative_question_service.ListGenerativeQuestionConfigsResponse, + ]: + r"""Return a callable for the list generative question + configs method over gRPC. + + Returns all questions for a given catalog. + + Returns: + Callable[[~.ListGenerativeQuestionConfigsRequest], + ~.ListGenerativeQuestionConfigsResponse]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "list_generative_question_configs" not in self._stubs: + self._stubs[ + "list_generative_question_configs" + ] = self.grpc_channel.unary_unary( + "/google.cloud.retail.v2alpha.GenerativeQuestionService/ListGenerativeQuestionConfigs", + request_serializer=generative_question_service.ListGenerativeQuestionConfigsRequest.serialize, + response_deserializer=generative_question_service.ListGenerativeQuestionConfigsResponse.deserialize, + ) + return self._stubs["list_generative_question_configs"] + + @property + def update_generative_question_config( + self, + ) -> Callable[ + [generative_question_service.UpdateGenerativeQuestionConfigRequest], + generative_question.GenerativeQuestionConfig, + ]: + r"""Return a callable for the update generative question + config method over gRPC. + + Allows management of individual questions. + + Returns: + Callable[[~.UpdateGenerativeQuestionConfigRequest], + ~.GenerativeQuestionConfig]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "update_generative_question_config" not in self._stubs: + self._stubs[ + "update_generative_question_config" + ] = self.grpc_channel.unary_unary( + "/google.cloud.retail.v2alpha.GenerativeQuestionService/UpdateGenerativeQuestionConfig", + request_serializer=generative_question_service.UpdateGenerativeQuestionConfigRequest.serialize, + response_deserializer=generative_question.GenerativeQuestionConfig.deserialize, + ) + return self._stubs["update_generative_question_config"] + + @property + def batch_update_generative_question_configs( + self, + ) -> Callable[ + [generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest], + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse, + ]: + r"""Return a callable for the batch update generative + question configs method over gRPC. + + Allows management of multiple questions. + + Returns: + Callable[[~.BatchUpdateGenerativeQuestionConfigsRequest], + ~.BatchUpdateGenerativeQuestionConfigsResponse]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "batch_update_generative_question_configs" not in self._stubs: + self._stubs[ + "batch_update_generative_question_configs" + ] = self.grpc_channel.unary_unary( + "/google.cloud.retail.v2alpha.GenerativeQuestionService/BatchUpdateGenerativeQuestionConfigs", + request_serializer=generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest.serialize, + response_deserializer=generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse.deserialize, + ) + return self._stubs["batch_update_generative_question_configs"] + + def close(self): + self.grpc_channel.close() + + @property + def get_operation( + self, + ) -> Callable[[operations_pb2.GetOperationRequest], operations_pb2.Operation]: + r"""Return a callable for the get_operation method over gRPC.""" + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "get_operation" not in self._stubs: + self._stubs["get_operation"] = self.grpc_channel.unary_unary( + "/google.longrunning.Operations/GetOperation", + request_serializer=operations_pb2.GetOperationRequest.SerializeToString, + response_deserializer=operations_pb2.Operation.FromString, + ) + return self._stubs["get_operation"] + + @property + def list_operations( + self, + ) -> Callable[ + [operations_pb2.ListOperationsRequest], operations_pb2.ListOperationsResponse + ]: + r"""Return a callable for the list_operations method over gRPC.""" + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "list_operations" not in self._stubs: + self._stubs["list_operations"] = self.grpc_channel.unary_unary( + "/google.longrunning.Operations/ListOperations", + request_serializer=operations_pb2.ListOperationsRequest.SerializeToString, + response_deserializer=operations_pb2.ListOperationsResponse.FromString, + ) + return self._stubs["list_operations"] + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("GenerativeQuestionServiceGrpcTransport",) diff --git a/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/generative_question_service/transports/grpc_asyncio.py b/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/generative_question_service/transports/grpc_asyncio.py new file mode 100644 index 000000000000..8f111352796a --- /dev/null +++ b/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/generative_question_service/transports/grpc_asyncio.py @@ -0,0 +1,481 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union +import warnings + +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1, grpc_helpers_async +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.cloud.location import locations_pb2 # type: ignore +from google.longrunning import operations_pb2 # type: ignore +import grpc # type: ignore +from grpc.experimental import aio # type: ignore + +from google.cloud.retail_v2alpha.types import ( + generative_question, + generative_question_service, +) + +from .base import DEFAULT_CLIENT_INFO, GenerativeQuestionServiceTransport +from .grpc import GenerativeQuestionServiceGrpcTransport + + +class GenerativeQuestionServiceGrpcAsyncIOTransport(GenerativeQuestionServiceTransport): + """gRPC AsyncIO backend transport for GenerativeQuestionService. + + Service for managing LLM generated questions in search + serving. + + This class defines the same methods as the primary client, so the + primary client can load the underlying transport implementation + and call it. + + It sends protocol buffers over the wire using gRPC (which is built on + top of HTTP/2); the ``grpcio`` package must be installed. + """ + + _grpc_channel: aio.Channel + _stubs: Dict[str, Callable] = {} + + @classmethod + def create_channel( + cls, + host: str = "retail.googleapis.com", + credentials: Optional[ga_credentials.Credentials] = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + quota_project_id: Optional[str] = None, + **kwargs, + ) -> aio.Channel: + """Create and return a gRPC AsyncIO channel object. + Args: + host (Optional[str]): The host for the channel to use. + credentials (Optional[~.Credentials]): The + authorization credentials to attach to requests. These + credentials identify this application to the service. If + none are specified, the client will attempt to ascertain + the credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + aio.Channel: A gRPC AsyncIO channel object. + """ + + return grpc_helpers_async.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + def __init__( + self, + *, + host: str = "retail.googleapis.com", + credentials: Optional[ga_credentials.Credentials] = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + channel: Optional[Union[aio.Channel, Callable[..., aio.Channel]]] = None, + api_mtls_endpoint: Optional[str] = None, + client_cert_source: Optional[Callable[[], Tuple[bytes, bytes]]] = None, + ssl_channel_credentials: Optional[grpc.ChannelCredentials] = None, + client_cert_source_for_mtls: Optional[Callable[[], Tuple[bytes, bytes]]] = None, + quota_project_id: Optional[str] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, + api_audience: Optional[str] = None, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to (default: 'retail.googleapis.com'). + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if a ``channel`` instance is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if a ``channel`` instance is provided. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + channel (Optional[Union[aio.Channel, Callable[..., aio.Channel]]]): + A ``Channel`` instance through which to make calls, or a Callable + that constructs and returns one. If set to None, ``self.create_channel`` + is used to create the channel. If a Callable is given, it will be called + with the same arguments as used in ``self.create_channel``. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if a ``channel`` instance is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if a ``channel`` instance or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn("client_cert_source is deprecated", DeprecationWarning) + + if isinstance(channel, aio.Channel): + # Ignore credentials if a channel was passed. + credentials = None + self._ignore_credentials = True + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + else: + self._ssl_channel_credentials = SslCredentials().ssl_credentials + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + api_audience=api_audience, + ) + + if not self._grpc_channel: + # initialize with the provided callable or the default channel + channel_init = channel or type(self).create_channel + self._grpc_channel = channel_init( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @property + def grpc_channel(self) -> aio.Channel: + """Create the channel designed to connect to this service. + + This property caches on the instance; repeated calls return + the same channel. + """ + # Return the channel from cache. + return self._grpc_channel + + @property + def update_generative_questions_feature_config( + self, + ) -> Callable[ + [generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest], + Awaitable[generative_question.GenerativeQuestionsFeatureConfig], + ]: + r"""Return a callable for the update generative questions + feature config method over gRPC. + + Manages overal generative question feature state -- + enables toggling feature on and off. + + Returns: + Callable[[~.UpdateGenerativeQuestionsFeatureConfigRequest], + Awaitable[~.GenerativeQuestionsFeatureConfig]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "update_generative_questions_feature_config" not in self._stubs: + self._stubs[ + "update_generative_questions_feature_config" + ] = self.grpc_channel.unary_unary( + "/google.cloud.retail.v2alpha.GenerativeQuestionService/UpdateGenerativeQuestionsFeatureConfig", + request_serializer=generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest.serialize, + response_deserializer=generative_question.GenerativeQuestionsFeatureConfig.deserialize, + ) + return self._stubs["update_generative_questions_feature_config"] + + @property + def get_generative_questions_feature_config( + self, + ) -> Callable[ + [generative_question_service.GetGenerativeQuestionsFeatureConfigRequest], + Awaitable[generative_question.GenerativeQuestionsFeatureConfig], + ]: + r"""Return a callable for the get generative questions + feature config method over gRPC. + + Manages overal generative question feature state -- + enables toggling feature on and off. + + Returns: + Callable[[~.GetGenerativeQuestionsFeatureConfigRequest], + Awaitable[~.GenerativeQuestionsFeatureConfig]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "get_generative_questions_feature_config" not in self._stubs: + self._stubs[ + "get_generative_questions_feature_config" + ] = self.grpc_channel.unary_unary( + "/google.cloud.retail.v2alpha.GenerativeQuestionService/GetGenerativeQuestionsFeatureConfig", + request_serializer=generative_question_service.GetGenerativeQuestionsFeatureConfigRequest.serialize, + response_deserializer=generative_question.GenerativeQuestionsFeatureConfig.deserialize, + ) + return self._stubs["get_generative_questions_feature_config"] + + @property + def list_generative_question_configs( + self, + ) -> Callable[ + [generative_question_service.ListGenerativeQuestionConfigsRequest], + Awaitable[generative_question_service.ListGenerativeQuestionConfigsResponse], + ]: + r"""Return a callable for the list generative question + configs method over gRPC. + + Returns all questions for a given catalog. + + Returns: + Callable[[~.ListGenerativeQuestionConfigsRequest], + Awaitable[~.ListGenerativeQuestionConfigsResponse]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "list_generative_question_configs" not in self._stubs: + self._stubs[ + "list_generative_question_configs" + ] = self.grpc_channel.unary_unary( + "/google.cloud.retail.v2alpha.GenerativeQuestionService/ListGenerativeQuestionConfigs", + request_serializer=generative_question_service.ListGenerativeQuestionConfigsRequest.serialize, + response_deserializer=generative_question_service.ListGenerativeQuestionConfigsResponse.deserialize, + ) + return self._stubs["list_generative_question_configs"] + + @property + def update_generative_question_config( + self, + ) -> Callable[ + [generative_question_service.UpdateGenerativeQuestionConfigRequest], + Awaitable[generative_question.GenerativeQuestionConfig], + ]: + r"""Return a callable for the update generative question + config method over gRPC. + + Allows management of individual questions. + + Returns: + Callable[[~.UpdateGenerativeQuestionConfigRequest], + Awaitable[~.GenerativeQuestionConfig]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "update_generative_question_config" not in self._stubs: + self._stubs[ + "update_generative_question_config" + ] = self.grpc_channel.unary_unary( + "/google.cloud.retail.v2alpha.GenerativeQuestionService/UpdateGenerativeQuestionConfig", + request_serializer=generative_question_service.UpdateGenerativeQuestionConfigRequest.serialize, + response_deserializer=generative_question.GenerativeQuestionConfig.deserialize, + ) + return self._stubs["update_generative_question_config"] + + @property + def batch_update_generative_question_configs( + self, + ) -> Callable[ + [generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest], + Awaitable[ + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse + ], + ]: + r"""Return a callable for the batch update generative + question configs method over gRPC. + + Allows management of multiple questions. + + Returns: + Callable[[~.BatchUpdateGenerativeQuestionConfigsRequest], + Awaitable[~.BatchUpdateGenerativeQuestionConfigsResponse]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "batch_update_generative_question_configs" not in self._stubs: + self._stubs[ + "batch_update_generative_question_configs" + ] = self.grpc_channel.unary_unary( + "/google.cloud.retail.v2alpha.GenerativeQuestionService/BatchUpdateGenerativeQuestionConfigs", + request_serializer=generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest.serialize, + response_deserializer=generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse.deserialize, + ) + return self._stubs["batch_update_generative_question_configs"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.update_generative_questions_feature_config: gapic_v1.method_async.wrap_method( + self.update_generative_questions_feature_config, + default_timeout=None, + client_info=client_info, + ), + self.get_generative_questions_feature_config: gapic_v1.method_async.wrap_method( + self.get_generative_questions_feature_config, + default_timeout=None, + client_info=client_info, + ), + self.list_generative_question_configs: gapic_v1.method_async.wrap_method( + self.list_generative_question_configs, + default_timeout=None, + client_info=client_info, + ), + self.update_generative_question_config: gapic_v1.method_async.wrap_method( + self.update_generative_question_config, + default_timeout=None, + client_info=client_info, + ), + self.batch_update_generative_question_configs: gapic_v1.method_async.wrap_method( + self.batch_update_generative_question_configs, + default_timeout=None, + client_info=client_info, + ), + } + + def close(self): + return self.grpc_channel.close() + + @property + def get_operation( + self, + ) -> Callable[[operations_pb2.GetOperationRequest], operations_pb2.Operation]: + r"""Return a callable for the get_operation method over gRPC.""" + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "get_operation" not in self._stubs: + self._stubs["get_operation"] = self.grpc_channel.unary_unary( + "/google.longrunning.Operations/GetOperation", + request_serializer=operations_pb2.GetOperationRequest.SerializeToString, + response_deserializer=operations_pb2.Operation.FromString, + ) + return self._stubs["get_operation"] + + @property + def list_operations( + self, + ) -> Callable[ + [operations_pb2.ListOperationsRequest], operations_pb2.ListOperationsResponse + ]: + r"""Return a callable for the list_operations method over gRPC.""" + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "list_operations" not in self._stubs: + self._stubs["list_operations"] = self.grpc_channel.unary_unary( + "/google.longrunning.Operations/ListOperations", + request_serializer=operations_pb2.ListOperationsRequest.SerializeToString, + response_deserializer=operations_pb2.ListOperationsResponse.FromString, + ) + return self._stubs["list_operations"] + + +__all__ = ("GenerativeQuestionServiceGrpcAsyncIOTransport",) diff --git a/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/generative_question_service/transports/rest.py b/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/generative_question_service/transports/rest.py new file mode 100644 index 000000000000..2e447751cd1c --- /dev/null +++ b/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/generative_question_service/transports/rest.py @@ -0,0 +1,1122 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +import dataclasses +import json # type: ignore +import re +from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple, Union +import warnings + +from google.api_core import gapic_v1, path_template, rest_helpers, rest_streaming +from google.api_core import exceptions as core_exceptions +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.transport.requests import AuthorizedSession # type: ignore +from google.cloud.location import locations_pb2 # type: ignore +from google.protobuf import json_format +import grpc # type: ignore +from requests import __version__ as requests_version + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault, None] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object, None] # type: ignore + + +from google.longrunning import operations_pb2 # type: ignore + +from google.cloud.retail_v2alpha.types import ( + generative_question, + generative_question_service, +) + +from .base import DEFAULT_CLIENT_INFO as BASE_DEFAULT_CLIENT_INFO +from .base import GenerativeQuestionServiceTransport + +DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=BASE_DEFAULT_CLIENT_INFO.gapic_version, + grpc_version=None, + rest_version=requests_version, +) + + +class GenerativeQuestionServiceRestInterceptor: + """Interceptor for GenerativeQuestionService. + + Interceptors are used to manipulate requests, request metadata, and responses + in arbitrary ways. + Example use cases include: + * Logging + * Verifying requests according to service or custom semantics + * Stripping extraneous information from responses + + These use cases and more can be enabled by injecting an + instance of a custom subclass when constructing the GenerativeQuestionServiceRestTransport. + + .. code-block:: python + class MyCustomGenerativeQuestionServiceInterceptor(GenerativeQuestionServiceRestInterceptor): + def pre_batch_update_generative_question_configs(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_batch_update_generative_question_configs(self, response): + logging.log(f"Received response: {response}") + return response + + def pre_get_generative_questions_feature_config(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_get_generative_questions_feature_config(self, response): + logging.log(f"Received response: {response}") + return response + + def pre_list_generative_question_configs(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_list_generative_question_configs(self, response): + logging.log(f"Received response: {response}") + return response + + def pre_update_generative_question_config(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_update_generative_question_config(self, response): + logging.log(f"Received response: {response}") + return response + + def pre_update_generative_questions_feature_config(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_update_generative_questions_feature_config(self, response): + logging.log(f"Received response: {response}") + return response + + transport = GenerativeQuestionServiceRestTransport(interceptor=MyCustomGenerativeQuestionServiceInterceptor()) + client = GenerativeQuestionServiceClient(transport=transport) + + + """ + + def pre_batch_update_generative_question_configs( + self, + request: generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[ + generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest, + Sequence[Tuple[str, str]], + ]: + """Pre-rpc interceptor for batch_update_generative_question_configs + + Override in a subclass to manipulate the request or metadata + before they are sent to the GenerativeQuestionService server. + """ + return request, metadata + + def post_batch_update_generative_question_configs( + self, + response: generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse, + ) -> generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse: + """Post-rpc interceptor for batch_update_generative_question_configs + + Override in a subclass to manipulate the response + after it is returned by the GenerativeQuestionService server but before + it is returned to user code. + """ + return response + + def pre_get_generative_questions_feature_config( + self, + request: generative_question_service.GetGenerativeQuestionsFeatureConfigRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[ + generative_question_service.GetGenerativeQuestionsFeatureConfigRequest, + Sequence[Tuple[str, str]], + ]: + """Pre-rpc interceptor for get_generative_questions_feature_config + + Override in a subclass to manipulate the request or metadata + before they are sent to the GenerativeQuestionService server. + """ + return request, metadata + + def post_get_generative_questions_feature_config( + self, response: generative_question.GenerativeQuestionsFeatureConfig + ) -> generative_question.GenerativeQuestionsFeatureConfig: + """Post-rpc interceptor for get_generative_questions_feature_config + + Override in a subclass to manipulate the response + after it is returned by the GenerativeQuestionService server but before + it is returned to user code. + """ + return response + + def pre_list_generative_question_configs( + self, + request: generative_question_service.ListGenerativeQuestionConfigsRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[ + generative_question_service.ListGenerativeQuestionConfigsRequest, + Sequence[Tuple[str, str]], + ]: + """Pre-rpc interceptor for list_generative_question_configs + + Override in a subclass to manipulate the request or metadata + before they are sent to the GenerativeQuestionService server. + """ + return request, metadata + + def post_list_generative_question_configs( + self, + response: generative_question_service.ListGenerativeQuestionConfigsResponse, + ) -> generative_question_service.ListGenerativeQuestionConfigsResponse: + """Post-rpc interceptor for list_generative_question_configs + + Override in a subclass to manipulate the response + after it is returned by the GenerativeQuestionService server but before + it is returned to user code. + """ + return response + + def pre_update_generative_question_config( + self, + request: generative_question_service.UpdateGenerativeQuestionConfigRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[ + generative_question_service.UpdateGenerativeQuestionConfigRequest, + Sequence[Tuple[str, str]], + ]: + """Pre-rpc interceptor for update_generative_question_config + + Override in a subclass to manipulate the request or metadata + before they are sent to the GenerativeQuestionService server. + """ + return request, metadata + + def post_update_generative_question_config( + self, response: generative_question.GenerativeQuestionConfig + ) -> generative_question.GenerativeQuestionConfig: + """Post-rpc interceptor for update_generative_question_config + + Override in a subclass to manipulate the response + after it is returned by the GenerativeQuestionService server but before + it is returned to user code. + """ + return response + + def pre_update_generative_questions_feature_config( + self, + request: generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[ + generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest, + Sequence[Tuple[str, str]], + ]: + """Pre-rpc interceptor for update_generative_questions_feature_config + + Override in a subclass to manipulate the request or metadata + before they are sent to the GenerativeQuestionService server. + """ + return request, metadata + + def post_update_generative_questions_feature_config( + self, response: generative_question.GenerativeQuestionsFeatureConfig + ) -> generative_question.GenerativeQuestionsFeatureConfig: + """Post-rpc interceptor for update_generative_questions_feature_config + + Override in a subclass to manipulate the response + after it is returned by the GenerativeQuestionService server but before + it is returned to user code. + """ + return response + + def pre_get_operation( + self, + request: operations_pb2.GetOperationRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[operations_pb2.GetOperationRequest, Sequence[Tuple[str, str]]]: + """Pre-rpc interceptor for get_operation + + Override in a subclass to manipulate the request or metadata + before they are sent to the GenerativeQuestionService server. + """ + return request, metadata + + def post_get_operation( + self, response: operations_pb2.Operation + ) -> operations_pb2.Operation: + """Post-rpc interceptor for get_operation + + Override in a subclass to manipulate the response + after it is returned by the GenerativeQuestionService server but before + it is returned to user code. + """ + return response + + def pre_list_operations( + self, + request: operations_pb2.ListOperationsRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[operations_pb2.ListOperationsRequest, Sequence[Tuple[str, str]]]: + """Pre-rpc interceptor for list_operations + + Override in a subclass to manipulate the request or metadata + before they are sent to the GenerativeQuestionService server. + """ + return request, metadata + + def post_list_operations( + self, response: operations_pb2.ListOperationsResponse + ) -> operations_pb2.ListOperationsResponse: + """Post-rpc interceptor for list_operations + + Override in a subclass to manipulate the response + after it is returned by the GenerativeQuestionService server but before + it is returned to user code. + """ + return response + + +@dataclasses.dataclass +class GenerativeQuestionServiceRestStub: + _session: AuthorizedSession + _host: str + _interceptor: GenerativeQuestionServiceRestInterceptor + + +class GenerativeQuestionServiceRestTransport(GenerativeQuestionServiceTransport): + """REST backend transport for GenerativeQuestionService. + + Service for managing LLM generated questions in search + serving. + + This class defines the same methods as the primary client, so the + primary client can load the underlying transport implementation + and call it. + + It sends JSON representations of protocol buffers over HTTP/1.1 + + """ + + def __init__( + self, + *, + host: str = "retail.googleapis.com", + credentials: Optional[ga_credentials.Credentials] = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + client_cert_source_for_mtls: Optional[Callable[[], Tuple[bytes, bytes]]] = None, + quota_project_id: Optional[str] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, + url_scheme: str = "https", + interceptor: Optional[GenerativeQuestionServiceRestInterceptor] = None, + api_audience: Optional[str] = None, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to (default: 'retail.googleapis.com'). + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + client_cert_source_for_mtls (Callable[[], Tuple[bytes, bytes]]): Client + certificate to configure mutual TLS HTTP channel. It is ignored + if ``channel`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you are developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + url_scheme: the protocol scheme for the API endpoint. Normally + "https", but for testing or local servers, + "http" can be specified. + """ + # Run the base constructor + # TODO(yon-mg): resolve other ctor params i.e. scopes, quota, etc. + # TODO: When custom host (api_endpoint) is set, `scopes` must *also* be set on the + # credentials object + maybe_url_match = re.match("^(?Phttp(?:s)?://)?(?P.*)$", host) + if maybe_url_match is None: + raise ValueError( + f"Unexpected hostname structure: {host}" + ) # pragma: NO COVER + + url_match_items = maybe_url_match.groupdict() + + host = f"{url_scheme}://{host}" if not url_match_items["scheme"] else host + + super().__init__( + host=host, + credentials=credentials, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + api_audience=api_audience, + ) + self._session = AuthorizedSession( + self._credentials, default_host=self.DEFAULT_HOST + ) + if client_cert_source_for_mtls: + self._session.configure_mtls_channel(client_cert_source_for_mtls) + self._interceptor = interceptor or GenerativeQuestionServiceRestInterceptor() + self._prep_wrapped_messages(client_info) + + class _BatchUpdateGenerativeQuestionConfigs(GenerativeQuestionServiceRestStub): + def __hash__(self): + return hash("BatchUpdateGenerativeQuestionConfigs") + + __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} + + @classmethod + def _get_unset_required_fields(cls, message_dict): + return { + k: v + for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items() + if k not in message_dict + } + + def __call__( + self, + request: generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse: + r"""Call the batch update generative + question configs method over HTTP. + + Args: + request (~.generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest): + The request object. Request for + BatchUpdateGenerativeQuestionConfig + method. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + ~.generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse: + Aggregated response for + UpdateGenerativeQuestionConfig method. + + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "post", + "uri": "/v2alpha/{parent=projects/*/locations/*/catalogs/*}/generativeQuestion:batchUpdate", + "body": "*", + }, + ] + ( + request, + metadata, + ) = self._interceptor.pre_batch_update_generative_question_configs( + request, metadata + ) + pb_request = generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest.pb( + request + ) + transcoded_request = path_template.transcode(http_options, pb_request) + + # Jsonify the request body + + body = json_format.MessageToJson( + transcoded_request["body"], use_integers_for_enums=True + ) + uri = transcoded_request["uri"] + method = transcoded_request["method"] + + # Jsonify the query params + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + use_integers_for_enums=True, + ) + ) + query_params.update(self._get_unset_required_fields(query_params)) + + query_params["$alt"] = "json;enum-encoding=int" + + # Send the request + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(self._session, method)( + "{host}{uri}".format(host=self._host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + data=body, + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + # Return the response + resp = ( + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse() + ) + pb_resp = generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse.pb( + resp + ) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + resp = self._interceptor.post_batch_update_generative_question_configs(resp) + return resp + + class _GetGenerativeQuestionsFeatureConfig(GenerativeQuestionServiceRestStub): + def __hash__(self): + return hash("GetGenerativeQuestionsFeatureConfig") + + __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} + + @classmethod + def _get_unset_required_fields(cls, message_dict): + return { + k: v + for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items() + if k not in message_dict + } + + def __call__( + self, + request: generative_question_service.GetGenerativeQuestionsFeatureConfigRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> generative_question.GenerativeQuestionsFeatureConfig: + r"""Call the get generative questions + feature config method over HTTP. + + Args: + request (~.generative_question_service.GetGenerativeQuestionsFeatureConfigRequest): + The request object. Request for + GetGenerativeQuestionsFeatureConfig + method. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + ~.generative_question.GenerativeQuestionsFeatureConfig: + Configuration for overall generative + question feature state. + + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "get", + "uri": "/v2alpha/{catalog=projects/*/locations/*/catalogs/*}/generativeQuestionFeature", + }, + ] + ( + request, + metadata, + ) = self._interceptor.pre_get_generative_questions_feature_config( + request, metadata + ) + pb_request = generative_question_service.GetGenerativeQuestionsFeatureConfigRequest.pb( + request + ) + transcoded_request = path_template.transcode(http_options, pb_request) + + uri = transcoded_request["uri"] + method = transcoded_request["method"] + + # Jsonify the query params + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + use_integers_for_enums=True, + ) + ) + query_params.update(self._get_unset_required_fields(query_params)) + + query_params["$alt"] = "json;enum-encoding=int" + + # Send the request + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(self._session, method)( + "{host}{uri}".format(host=self._host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + # Return the response + resp = generative_question.GenerativeQuestionsFeatureConfig() + pb_resp = generative_question.GenerativeQuestionsFeatureConfig.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + resp = self._interceptor.post_get_generative_questions_feature_config(resp) + return resp + + class _ListGenerativeQuestionConfigs(GenerativeQuestionServiceRestStub): + def __hash__(self): + return hash("ListGenerativeQuestionConfigs") + + __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} + + @classmethod + def _get_unset_required_fields(cls, message_dict): + return { + k: v + for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items() + if k not in message_dict + } + + def __call__( + self, + request: generative_question_service.ListGenerativeQuestionConfigsRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> generative_question_service.ListGenerativeQuestionConfigsResponse: + r"""Call the list generative question + configs method over HTTP. + + Args: + request (~.generative_question_service.ListGenerativeQuestionConfigsRequest): + The request object. Request for ListQuestions method. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + ~.generative_question_service.ListGenerativeQuestionConfigsResponse: + Response for ListQuestions method. + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "get", + "uri": "/v2alpha/{parent=projects/*/locations/*/catalogs/*}/generativeQuestions", + }, + ] + request, metadata = self._interceptor.pre_list_generative_question_configs( + request, metadata + ) + pb_request = ( + generative_question_service.ListGenerativeQuestionConfigsRequest.pb( + request + ) + ) + transcoded_request = path_template.transcode(http_options, pb_request) + + uri = transcoded_request["uri"] + method = transcoded_request["method"] + + # Jsonify the query params + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + use_integers_for_enums=True, + ) + ) + query_params.update(self._get_unset_required_fields(query_params)) + + query_params["$alt"] = "json;enum-encoding=int" + + # Send the request + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(self._session, method)( + "{host}{uri}".format(host=self._host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + # Return the response + resp = generative_question_service.ListGenerativeQuestionConfigsResponse() + pb_resp = ( + generative_question_service.ListGenerativeQuestionConfigsResponse.pb( + resp + ) + ) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + resp = self._interceptor.post_list_generative_question_configs(resp) + return resp + + class _UpdateGenerativeQuestionConfig(GenerativeQuestionServiceRestStub): + def __hash__(self): + return hash("UpdateGenerativeQuestionConfig") + + __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} + + @classmethod + def _get_unset_required_fields(cls, message_dict): + return { + k: v + for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items() + if k not in message_dict + } + + def __call__( + self, + request: generative_question_service.UpdateGenerativeQuestionConfigRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> generative_question.GenerativeQuestionConfig: + r"""Call the update generative + question config method over HTTP. + + Args: + request (~.generative_question_service.UpdateGenerativeQuestionConfigRequest): + The request object. Request for + UpdateGenerativeQuestionConfig method. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + ~.generative_question.GenerativeQuestionConfig: + Configuration for a single generated + question. + + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "patch", + "uri": "/v2alpha/{generative_question_config.catalog=projects/*/locations/*/catalogs/*}/generativeQuestion", + "body": "generative_question_config", + }, + ] + request, metadata = self._interceptor.pre_update_generative_question_config( + request, metadata + ) + pb_request = ( + generative_question_service.UpdateGenerativeQuestionConfigRequest.pb( + request + ) + ) + transcoded_request = path_template.transcode(http_options, pb_request) + + # Jsonify the request body + + body = json_format.MessageToJson( + transcoded_request["body"], use_integers_for_enums=True + ) + uri = transcoded_request["uri"] + method = transcoded_request["method"] + + # Jsonify the query params + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + use_integers_for_enums=True, + ) + ) + query_params.update(self._get_unset_required_fields(query_params)) + + query_params["$alt"] = "json;enum-encoding=int" + + # Send the request + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(self._session, method)( + "{host}{uri}".format(host=self._host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + data=body, + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + # Return the response + resp = generative_question.GenerativeQuestionConfig() + pb_resp = generative_question.GenerativeQuestionConfig.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + resp = self._interceptor.post_update_generative_question_config(resp) + return resp + + class _UpdateGenerativeQuestionsFeatureConfig(GenerativeQuestionServiceRestStub): + def __hash__(self): + return hash("UpdateGenerativeQuestionsFeatureConfig") + + __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} + + @classmethod + def _get_unset_required_fields(cls, message_dict): + return { + k: v + for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items() + if k not in message_dict + } + + def __call__( + self, + request: generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> generative_question.GenerativeQuestionsFeatureConfig: + r"""Call the update generative + questions feature config method over HTTP. + + Args: + request (~.generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest): + The request object. Request for + UpdateGenerativeQuestionsFeatureConfig + method. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + ~.generative_question.GenerativeQuestionsFeatureConfig: + Configuration for overall generative + question feature state. + + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "patch", + "uri": "/v2alpha/{generative_questions_feature_config.catalog=projects/*/locations/*/catalogs/*}/generativeQuestionFeature", + "body": "generative_questions_feature_config", + }, + ] + ( + request, + metadata, + ) = self._interceptor.pre_update_generative_questions_feature_config( + request, metadata + ) + pb_request = generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest.pb( + request + ) + transcoded_request = path_template.transcode(http_options, pb_request) + + # Jsonify the request body + + body = json_format.MessageToJson( + transcoded_request["body"], use_integers_for_enums=True + ) + uri = transcoded_request["uri"] + method = transcoded_request["method"] + + # Jsonify the query params + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + use_integers_for_enums=True, + ) + ) + query_params.update(self._get_unset_required_fields(query_params)) + + query_params["$alt"] = "json;enum-encoding=int" + + # Send the request + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(self._session, method)( + "{host}{uri}".format(host=self._host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + data=body, + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + # Return the response + resp = generative_question.GenerativeQuestionsFeatureConfig() + pb_resp = generative_question.GenerativeQuestionsFeatureConfig.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + resp = self._interceptor.post_update_generative_questions_feature_config( + resp + ) + return resp + + @property + def batch_update_generative_question_configs( + self, + ) -> Callable[ + [generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest], + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse, + ]: + # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here. + # In C++ this would require a dynamic_cast + return self._BatchUpdateGenerativeQuestionConfigs(self._session, self._host, self._interceptor) # type: ignore + + @property + def get_generative_questions_feature_config( + self, + ) -> Callable[ + [generative_question_service.GetGenerativeQuestionsFeatureConfigRequest], + generative_question.GenerativeQuestionsFeatureConfig, + ]: + # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here. + # In C++ this would require a dynamic_cast + return self._GetGenerativeQuestionsFeatureConfig(self._session, self._host, self._interceptor) # type: ignore + + @property + def list_generative_question_configs( + self, + ) -> Callable[ + [generative_question_service.ListGenerativeQuestionConfigsRequest], + generative_question_service.ListGenerativeQuestionConfigsResponse, + ]: + # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here. + # In C++ this would require a dynamic_cast + return self._ListGenerativeQuestionConfigs(self._session, self._host, self._interceptor) # type: ignore + + @property + def update_generative_question_config( + self, + ) -> Callable[ + [generative_question_service.UpdateGenerativeQuestionConfigRequest], + generative_question.GenerativeQuestionConfig, + ]: + # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here. + # In C++ this would require a dynamic_cast + return self._UpdateGenerativeQuestionConfig(self._session, self._host, self._interceptor) # type: ignore + + @property + def update_generative_questions_feature_config( + self, + ) -> Callable[ + [generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest], + generative_question.GenerativeQuestionsFeatureConfig, + ]: + # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here. + # In C++ this would require a dynamic_cast + return self._UpdateGenerativeQuestionsFeatureConfig(self._session, self._host, self._interceptor) # type: ignore + + @property + def get_operation(self): + return self._GetOperation(self._session, self._host, self._interceptor) # type: ignore + + class _GetOperation(GenerativeQuestionServiceRestStub): + def __call__( + self, + request: operations_pb2.GetOperationRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operations_pb2.Operation: + r"""Call the get operation method over HTTP. + + Args: + request (operations_pb2.GetOperationRequest): + The request object for GetOperation method. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + operations_pb2.Operation: Response from GetOperation method. + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "get", + "uri": "/v2alpha/{name=projects/*/locations/*/catalogs/*/branches/*/operations/*}", + }, + { + "method": "get", + "uri": "/v2alpha/{name=projects/*/locations/*/catalogs/*/branches/*/places/*/operations/*}", + }, + { + "method": "get", + "uri": "/v2alpha/{name=projects/*/locations/*/catalogs/*/operations/*}", + }, + { + "method": "get", + "uri": "/v2alpha/{name=projects/*/locations/*/operations/*}", + }, + { + "method": "get", + "uri": "/v2alpha/{name=projects/*/operations/*}", + }, + ] + + request, metadata = self._interceptor.pre_get_operation(request, metadata) + request_kwargs = json_format.MessageToDict(request) + transcoded_request = path_template.transcode(http_options, **request_kwargs) + + uri = transcoded_request["uri"] + method = transcoded_request["method"] + + # Jsonify the query params + query_params = json.loads(json.dumps(transcoded_request["query_params"])) + + # Send the request + headers = dict(metadata) + headers["Content-Type"] = "application/json" + + response = getattr(self._session, method)( + "{host}{uri}".format(host=self._host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params), + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + resp = operations_pb2.Operation() + resp = json_format.Parse(response.content.decode("utf-8"), resp) + resp = self._interceptor.post_get_operation(resp) + return resp + + @property + def list_operations(self): + return self._ListOperations(self._session, self._host, self._interceptor) # type: ignore + + class _ListOperations(GenerativeQuestionServiceRestStub): + def __call__( + self, + request: operations_pb2.ListOperationsRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operations_pb2.ListOperationsResponse: + r"""Call the list operations method over HTTP. + + Args: + request (operations_pb2.ListOperationsRequest): + The request object for ListOperations method. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + operations_pb2.ListOperationsResponse: Response from ListOperations method. + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "get", + "uri": "/v2alpha/{name=projects/*/locations/*/catalogs/*}/operations", + }, + { + "method": "get", + "uri": "/v2alpha/{name=projects/*/locations/*}/operations", + }, + { + "method": "get", + "uri": "/v2alpha/{name=projects/*}/operations", + }, + ] + + request, metadata = self._interceptor.pre_list_operations(request, metadata) + request_kwargs = json_format.MessageToDict(request) + transcoded_request = path_template.transcode(http_options, **request_kwargs) + + uri = transcoded_request["uri"] + method = transcoded_request["method"] + + # Jsonify the query params + query_params = json.loads(json.dumps(transcoded_request["query_params"])) + + # Send the request + headers = dict(metadata) + headers["Content-Type"] = "application/json" + + response = getattr(self._session, method)( + "{host}{uri}".format(host=self._host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params), + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + resp = operations_pb2.ListOperationsResponse() + resp = json_format.Parse(response.content.decode("utf-8"), resp) + resp = self._interceptor.post_list_operations(resp) + return resp + + @property + def kind(self) -> str: + return "rest" + + def close(self): + self._session.close() + + +__all__ = ("GenerativeQuestionServiceRestTransport",) diff --git a/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/product_service/async_client.py b/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/product_service/async_client.py index 59dc8c92da80..99bff0168e59 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/product_service/async_client.py +++ b/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/product_service/async_client.py @@ -52,8 +52,8 @@ from google.protobuf import wrappers_pb2 # type: ignore from google.cloud.retail_v2alpha.services.product_service import pagers +from google.cloud.retail_v2alpha.types import common, export_config, import_config from google.cloud.retail_v2alpha.types import product_service, promotion, purge_config -from google.cloud.retail_v2alpha.types import common, import_config from google.cloud.retail_v2alpha.types import product from google.cloud.retail_v2alpha.types import product as gcr_product @@ -1163,6 +1163,111 @@ async def sample_import_products(): # Done; return the response. return response + async def export_products( + self, + request: Optional[Union[export_config.ExportProductsRequest, dict]] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operation_async.AsyncOperation: + r"""Exports multiple + [Product][google.cloud.retail.v2alpha.Product]s. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import retail_v2alpha + + async def sample_export_products(): + # Create a client + client = retail_v2alpha.ProductServiceAsyncClient() + + # Initialize request argument(s) + output_config = retail_v2alpha.OutputConfig() + output_config.gcs_destination.output_uri_prefix = "output_uri_prefix_value" + + request = retail_v2alpha.ExportProductsRequest( + parent="parent_value", + output_config=output_config, + ) + + # Make the request + operation = client.export_products(request=request) + + print("Waiting for operation to complete...") + + response = (await operation).result() + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.retail_v2alpha.types.ExportProductsRequest, dict]]): + The request object. Request message for ExportProducts + method. + retry (google.api_core.retry_async.AsyncRetry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.api_core.operation_async.AsyncOperation: + An object representing a long-running operation. + + The result type for the operation will be :class:`google.cloud.retail_v2alpha.types.ExportProductsResponse` Response of the ExportProductsRequest. If the long running + operation is done, then this message is returned by + the google.longrunning.Operations.response field if + the operation was successful. + + """ + # Create or coerce a protobuf request object. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, export_config.ExportProductsRequest): + request = export_config.ExportProductsRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.export_products + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Wrap the response in an operation future. + response = operation_async.from_gapic( + response, + self._client._transport.operations_client, + export_config.ExportProductsResponse, + metadata_type=export_config.ExportMetadata, + ) + + # Done; return the response. + return response + async def set_inventory( self, request: Optional[Union[product_service.SetInventoryRequest, dict]] = None, diff --git a/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/product_service/client.py b/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/product_service/client.py index a952d57b1fd8..1069d783b54e 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/product_service/client.py +++ b/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/product_service/client.py @@ -58,8 +58,8 @@ from google.protobuf import wrappers_pb2 # type: ignore from google.cloud.retail_v2alpha.services.product_service import pagers +from google.cloud.retail_v2alpha.types import common, export_config, import_config from google.cloud.retail_v2alpha.types import product_service, promotion, purge_config -from google.cloud.retail_v2alpha.types import common, import_config from google.cloud.retail_v2alpha.types import product from google.cloud.retail_v2alpha.types import product as gcr_product @@ -1593,6 +1593,109 @@ def sample_import_products(): # Done; return the response. return response + def export_products( + self, + request: Optional[Union[export_config.ExportProductsRequest, dict]] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operation.Operation: + r"""Exports multiple + [Product][google.cloud.retail.v2alpha.Product]s. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import retail_v2alpha + + def sample_export_products(): + # Create a client + client = retail_v2alpha.ProductServiceClient() + + # Initialize request argument(s) + output_config = retail_v2alpha.OutputConfig() + output_config.gcs_destination.output_uri_prefix = "output_uri_prefix_value" + + request = retail_v2alpha.ExportProductsRequest( + parent="parent_value", + output_config=output_config, + ) + + # Make the request + operation = client.export_products(request=request) + + print("Waiting for operation to complete...") + + response = operation.result() + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.retail_v2alpha.types.ExportProductsRequest, dict]): + The request object. Request message for ExportProducts + method. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.api_core.operation.Operation: + An object representing a long-running operation. + + The result type for the operation will be :class:`google.cloud.retail_v2alpha.types.ExportProductsResponse` Response of the ExportProductsRequest. If the long running + operation is done, then this message is returned by + the google.longrunning.Operations.response field if + the operation was successful. + + """ + # Create or coerce a protobuf request object. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, export_config.ExportProductsRequest): + request = export_config.ExportProductsRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.export_products] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Wrap the response in an operation future. + response = operation.from_gapic( + response, + self._transport.operations_client, + export_config.ExportProductsResponse, + metadata_type=export_config.ExportMetadata, + ) + + # Done; return the response. + return response + def set_inventory( self, request: Optional[Union[product_service.SetInventoryRequest, dict]] = None, diff --git a/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/product_service/transports/base.py b/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/product_service/transports/base.py index 0e64ea512ae7..c9edcebbfb32 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/product_service/transports/base.py +++ b/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/product_service/transports/base.py @@ -28,7 +28,7 @@ from google.protobuf import empty_pb2 # type: ignore from google.cloud.retail_v2alpha import gapic_version as package_version -from google.cloud.retail_v2alpha.types import import_config +from google.cloud.retail_v2alpha.types import export_config, import_config from google.cloud.retail_v2alpha.types import product from google.cloud.retail_v2alpha.types import product as gcr_product from google.cloud.retail_v2alpha.types import product_service, purge_config @@ -179,6 +179,11 @@ def _prep_wrapped_messages(self, client_info): default_timeout=300.0, client_info=client_info, ), + self.export_products: gapic_v1.method.wrap_method( + self.export_products, + default_timeout=None, + client_info=client_info, + ), self.set_inventory: gapic_v1.method.wrap_method( self.set_inventory, default_timeout=None, @@ -286,6 +291,15 @@ def import_products( ]: raise NotImplementedError() + @property + def export_products( + self, + ) -> Callable[ + [export_config.ExportProductsRequest], + Union[operations_pb2.Operation, Awaitable[operations_pb2.Operation]], + ]: + raise NotImplementedError() + @property def set_inventory( self, diff --git a/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/product_service/transports/grpc.py b/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/product_service/transports/grpc.py index 995b88e1d925..8614dd3dfd8b 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/product_service/transports/grpc.py +++ b/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/product_service/transports/grpc.py @@ -25,7 +25,7 @@ from google.protobuf import empty_pb2 # type: ignore import grpc # type: ignore -from google.cloud.retail_v2alpha.types import import_config +from google.cloud.retail_v2alpha.types import export_config, import_config from google.cloud.retail_v2alpha.types import product from google.cloud.retail_v2alpha.types import product as gcr_product from google.cloud.retail_v2alpha.types import product_service, purge_config @@ -467,6 +467,33 @@ def import_products( ) return self._stubs["import_products"] + @property + def export_products( + self, + ) -> Callable[[export_config.ExportProductsRequest], operations_pb2.Operation]: + r"""Return a callable for the export products method over gRPC. + + Exports multiple + [Product][google.cloud.retail.v2alpha.Product]s. + + Returns: + Callable[[~.ExportProductsRequest], + ~.Operation]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "export_products" not in self._stubs: + self._stubs["export_products"] = self.grpc_channel.unary_unary( + "/google.cloud.retail.v2alpha.ProductService/ExportProducts", + request_serializer=export_config.ExportProductsRequest.serialize, + response_deserializer=operations_pb2.Operation.FromString, + ) + return self._stubs["export_products"] + @property def set_inventory( self, diff --git a/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/product_service/transports/grpc_asyncio.py b/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/product_service/transports/grpc_asyncio.py index b742b9eb1467..816ed462163a 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/product_service/transports/grpc_asyncio.py +++ b/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/product_service/transports/grpc_asyncio.py @@ -27,7 +27,7 @@ import grpc # type: ignore from grpc.experimental import aio # type: ignore -from google.cloud.retail_v2alpha.types import import_config +from google.cloud.retail_v2alpha.types import export_config, import_config from google.cloud.retail_v2alpha.types import product from google.cloud.retail_v2alpha.types import product as gcr_product from google.cloud.retail_v2alpha.types import product_service, purge_config @@ -482,6 +482,35 @@ def import_products( ) return self._stubs["import_products"] + @property + def export_products( + self, + ) -> Callable[ + [export_config.ExportProductsRequest], Awaitable[operations_pb2.Operation] + ]: + r"""Return a callable for the export products method over gRPC. + + Exports multiple + [Product][google.cloud.retail.v2alpha.Product]s. + + Returns: + Callable[[~.ExportProductsRequest], + Awaitable[~.Operation]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "export_products" not in self._stubs: + self._stubs["export_products"] = self.grpc_channel.unary_unary( + "/google.cloud.retail.v2alpha.ProductService/ExportProducts", + request_serializer=export_config.ExportProductsRequest.serialize, + response_deserializer=operations_pb2.Operation.FromString, + ) + return self._stubs["export_products"] + @property def set_inventory( self, @@ -847,6 +876,11 @@ def _prep_wrapped_messages(self, client_info): default_timeout=300.0, client_info=client_info, ), + self.export_products: gapic_v1.method_async.wrap_method( + self.export_products, + default_timeout=None, + client_info=client_info, + ), self.set_inventory: gapic_v1.method_async.wrap_method( self.set_inventory, default_timeout=None, diff --git a/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/product_service/transports/rest.py b/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/product_service/transports/rest.py index bed4864551fd..5467af6d9848 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/product_service/transports/rest.py +++ b/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/product_service/transports/rest.py @@ -46,7 +46,7 @@ from google.longrunning import operations_pb2 # type: ignore from google.protobuf import empty_pb2 # type: ignore -from google.cloud.retail_v2alpha.types import import_config +from google.cloud.retail_v2alpha.types import export_config, import_config from google.cloud.retail_v2alpha.types import product from google.cloud.retail_v2alpha.types import product as gcr_product from google.cloud.retail_v2alpha.types import product_service, purge_config @@ -104,6 +104,14 @@ def pre_delete_product(self, request, metadata): logging.log(f"Received request: {request}") return request, metadata + def pre_export_products(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_export_products(self, response): + logging.log(f"Received response: {response}") + return response + def pre_get_product(self, request, metadata): logging.log(f"Received request: {request}") return request, metadata @@ -253,6 +261,29 @@ def pre_delete_product( """ return request, metadata + def pre_export_products( + self, + request: export_config.ExportProductsRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[export_config.ExportProductsRequest, Sequence[Tuple[str, str]]]: + """Pre-rpc interceptor for export_products + + Override in a subclass to manipulate the request or metadata + before they are sent to the ProductService server. + """ + return request, metadata + + def post_export_products( + self, response: operations_pb2.Operation + ) -> operations_pb2.Operation: + """Post-rpc interceptor for export_products + + Override in a subclass to manipulate the response + after it is returned by the ProductService server but before + it is returned to user code. + """ + return response + def pre_get_product( self, request: product_service.GetProductRequest, @@ -1014,6 +1045,100 @@ def __call__( if response.status_code >= 400: raise core_exceptions.from_http_response(response) + class _ExportProducts(ProductServiceRestStub): + def __hash__(self): + return hash("ExportProducts") + + __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} + + @classmethod + def _get_unset_required_fields(cls, message_dict): + return { + k: v + for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items() + if k not in message_dict + } + + def __call__( + self, + request: export_config.ExportProductsRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operations_pb2.Operation: + r"""Call the export products method over HTTP. + + Args: + request (~.export_config.ExportProductsRequest): + The request object. Request message for ExportProducts + method. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + ~.operations_pb2.Operation: + This resource represents a + long-running operation that is the + result of a network API call. + + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "post", + "uri": "/v2alpha/{parent=projects/*/locations/*/catalogs/*/branches/*}/products:export", + "body": "*", + }, + ] + request, metadata = self._interceptor.pre_export_products(request, metadata) + pb_request = export_config.ExportProductsRequest.pb(request) + transcoded_request = path_template.transcode(http_options, pb_request) + + # Jsonify the request body + + body = json_format.MessageToJson( + transcoded_request["body"], use_integers_for_enums=True + ) + uri = transcoded_request["uri"] + method = transcoded_request["method"] + + # Jsonify the query params + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + use_integers_for_enums=True, + ) + ) + query_params.update(self._get_unset_required_fields(query_params)) + + query_params["$alt"] = "json;enum-encoding=int" + + # Send the request + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(self._session, method)( + "{host}{uri}".format(host=self._host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + data=body, + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + # Return the response + resp = operations_pb2.Operation() + json_format.Parse(response.content, resp, ignore_unknown_fields=True) + resp = self._interceptor.post_export_products(resp) + return resp + class _GetProduct(ProductServiceRestStub): def __hash__(self): return hash("GetProduct") @@ -1803,6 +1928,14 @@ def delete_product( # In C++ this would require a dynamic_cast return self._DeleteProduct(self._session, self._host, self._interceptor) # type: ignore + @property + def export_products( + self, + ) -> Callable[[export_config.ExportProductsRequest], operations_pb2.Operation]: + # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here. + # In C++ this would require a dynamic_cast + return self._ExportProducts(self._session, self._host, self._interceptor) # type: ignore + @property def get_product( self, diff --git a/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/user_event_service/async_client.py b/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/user_event_service/async_client.py index 607b3d2a8c35..4c9c6fafcfc7 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/user_event_service/async_client.py +++ b/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/user_event_service/async_client.py @@ -52,6 +52,7 @@ from google.cloud.retail_v2alpha.types import ( common, + export_config, import_config, purge_config, user_event, @@ -718,6 +719,113 @@ async def sample_import_user_events(): # Done; return the response. return response + async def export_user_events( + self, + request: Optional[Union[export_config.ExportUserEventsRequest, dict]] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operation_async.AsyncOperation: + r"""Exports user events. + + ``Operation.response`` is of type ``ExportResponse``. + ``Operation.metadata`` is of type ``ExportMetadata``. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import retail_v2alpha + + async def sample_export_user_events(): + # Create a client + client = retail_v2alpha.UserEventServiceAsyncClient() + + # Initialize request argument(s) + output_config = retail_v2alpha.OutputConfig() + output_config.gcs_destination.output_uri_prefix = "output_uri_prefix_value" + + request = retail_v2alpha.ExportUserEventsRequest( + parent="parent_value", + output_config=output_config, + ) + + # Make the request + operation = client.export_user_events(request=request) + + print("Waiting for operation to complete...") + + response = (await operation).result() + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.retail_v2alpha.types.ExportUserEventsRequest, dict]]): + The request object. Request message for the ``ExportUserEvents`` method. + retry (google.api_core.retry_async.AsyncRetry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.api_core.operation_async.AsyncOperation: + An object representing a long-running operation. + + The result type for the operation will be :class:`google.cloud.retail_v2alpha.types.ExportUserEventsResponse` Response of the ExportUserEventsRequest. If the long running + operation was successful, then this message is + returned by the + google.longrunning.Operations.response field if the + operation was successful. + + """ + # Create or coerce a protobuf request object. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, export_config.ExportUserEventsRequest): + request = export_config.ExportUserEventsRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.export_user_events + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Wrap the response in an operation future. + response = operation_async.from_gapic( + response, + self._client._transport.operations_client, + export_config.ExportUserEventsResponse, + metadata_type=export_config.ExportMetadata, + ) + + # Done; return the response. + return response + async def rejoin_user_events( self, request: Optional[ diff --git a/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/user_event_service/client.py b/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/user_event_service/client.py index c6c20f65085f..5e0e66e7373f 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/user_event_service/client.py +++ b/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/user_event_service/client.py @@ -58,6 +58,7 @@ from google.cloud.retail_v2alpha.types import ( common, + export_config, import_config, purge_config, user_event, @@ -1158,6 +1159,111 @@ def sample_import_user_events(): # Done; return the response. return response + def export_user_events( + self, + request: Optional[Union[export_config.ExportUserEventsRequest, dict]] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operation.Operation: + r"""Exports user events. + + ``Operation.response`` is of type ``ExportResponse``. + ``Operation.metadata`` is of type ``ExportMetadata``. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import retail_v2alpha + + def sample_export_user_events(): + # Create a client + client = retail_v2alpha.UserEventServiceClient() + + # Initialize request argument(s) + output_config = retail_v2alpha.OutputConfig() + output_config.gcs_destination.output_uri_prefix = "output_uri_prefix_value" + + request = retail_v2alpha.ExportUserEventsRequest( + parent="parent_value", + output_config=output_config, + ) + + # Make the request + operation = client.export_user_events(request=request) + + print("Waiting for operation to complete...") + + response = operation.result() + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.retail_v2alpha.types.ExportUserEventsRequest, dict]): + The request object. Request message for the ``ExportUserEvents`` method. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.api_core.operation.Operation: + An object representing a long-running operation. + + The result type for the operation will be :class:`google.cloud.retail_v2alpha.types.ExportUserEventsResponse` Response of the ExportUserEventsRequest. If the long running + operation was successful, then this message is + returned by the + google.longrunning.Operations.response field if the + operation was successful. + + """ + # Create or coerce a protobuf request object. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, export_config.ExportUserEventsRequest): + request = export_config.ExportUserEventsRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.export_user_events] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Wrap the response in an operation future. + response = operation.from_gapic( + response, + self._transport.operations_client, + export_config.ExportUserEventsResponse, + metadata_type=export_config.ExportMetadata, + ) + + # Done; return the response. + return response + def rejoin_user_events( self, request: Optional[ diff --git a/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/user_event_service/transports/base.py b/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/user_event_service/transports/base.py index 41a23390a00c..660110bffb30 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/user_event_service/transports/base.py +++ b/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/user_event_service/transports/base.py @@ -29,6 +29,7 @@ from google.cloud.retail_v2alpha import gapic_version as package_version from google.cloud.retail_v2alpha.types import ( + export_config, import_config, purge_config, user_event, @@ -176,6 +177,11 @@ def _prep_wrapped_messages(self, client_info): default_timeout=600.0, client_info=client_info, ), + self.export_user_events: gapic_v1.method.wrap_method( + self.export_user_events, + default_timeout=None, + client_info=client_info, + ), self.rejoin_user_events: gapic_v1.method.wrap_method( self.rejoin_user_events, default_timeout=None, @@ -233,6 +239,15 @@ def import_user_events( ]: raise NotImplementedError() + @property + def export_user_events( + self, + ) -> Callable[ + [export_config.ExportUserEventsRequest], + Union[operations_pb2.Operation, Awaitable[operations_pb2.Operation]], + ]: + raise NotImplementedError() + @property def rejoin_user_events( self, diff --git a/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/user_event_service/transports/grpc.py b/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/user_event_service/transports/grpc.py index 1e66bcdfc6fb..cf586fbb4a3f 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/user_event_service/transports/grpc.py +++ b/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/user_event_service/transports/grpc.py @@ -26,6 +26,7 @@ import grpc # type: ignore from google.cloud.retail_v2alpha.types import ( + export_config, import_config, purge_config, user_event, @@ -378,6 +379,35 @@ def import_user_events( ) return self._stubs["import_user_events"] + @property + def export_user_events( + self, + ) -> Callable[[export_config.ExportUserEventsRequest], operations_pb2.Operation]: + r"""Return a callable for the export user events method over gRPC. + + Exports user events. + + ``Operation.response`` is of type ``ExportResponse``. + ``Operation.metadata`` is of type ``ExportMetadata``. + + Returns: + Callable[[~.ExportUserEventsRequest], + ~.Operation]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "export_user_events" not in self._stubs: + self._stubs["export_user_events"] = self.grpc_channel.unary_unary( + "/google.cloud.retail.v2alpha.UserEventService/ExportUserEvents", + request_serializer=export_config.ExportUserEventsRequest.serialize, + response_deserializer=operations_pb2.Operation.FromString, + ) + return self._stubs["export_user_events"] + @property def rejoin_user_events( self, diff --git a/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/user_event_service/transports/grpc_asyncio.py b/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/user_event_service/transports/grpc_asyncio.py index 24cd974e4042..8d6dc52881df 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/user_event_service/transports/grpc_asyncio.py +++ b/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/user_event_service/transports/grpc_asyncio.py @@ -28,6 +28,7 @@ from grpc.experimental import aio # type: ignore from google.cloud.retail_v2alpha.types import ( + export_config, import_config, purge_config, user_event, @@ -392,6 +393,37 @@ def import_user_events( ) return self._stubs["import_user_events"] + @property + def export_user_events( + self, + ) -> Callable[ + [export_config.ExportUserEventsRequest], Awaitable[operations_pb2.Operation] + ]: + r"""Return a callable for the export user events method over gRPC. + + Exports user events. + + ``Operation.response`` is of type ``ExportResponse``. + ``Operation.metadata`` is of type ``ExportMetadata``. + + Returns: + Callable[[~.ExportUserEventsRequest], + Awaitable[~.Operation]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "export_user_events" not in self._stubs: + self._stubs["export_user_events"] = self.grpc_channel.unary_unary( + "/google.cloud.retail.v2alpha.UserEventService/ExportUserEvents", + request_serializer=export_config.ExportUserEventsRequest.serialize, + response_deserializer=operations_pb2.Operation.FromString, + ) + return self._stubs["export_user_events"] + @property def rejoin_user_events( self, @@ -474,6 +506,11 @@ def _prep_wrapped_messages(self, client_info): default_timeout=600.0, client_info=client_info, ), + self.export_user_events: gapic_v1.method_async.wrap_method( + self.export_user_events, + default_timeout=None, + client_info=client_info, + ), self.rejoin_user_events: gapic_v1.method_async.wrap_method( self.rejoin_user_events, default_timeout=None, diff --git a/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/user_event_service/transports/rest.py b/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/user_event_service/transports/rest.py index 17bcfa855bc3..5158149dd07e 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/user_event_service/transports/rest.py +++ b/packages/google-cloud-retail/google/cloud/retail_v2alpha/services/user_event_service/transports/rest.py @@ -47,6 +47,7 @@ from google.longrunning import operations_pb2 # type: ignore from google.cloud.retail_v2alpha.types import ( + export_config, import_config, purge_config, user_event, @@ -86,6 +87,14 @@ def post_collect_user_event(self, response): logging.log(f"Received response: {response}") return response + def pre_export_user_events(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_export_user_events(self, response): + logging.log(f"Received response: {response}") + return response + def pre_import_user_events(self, request, metadata): logging.log(f"Received request: {request}") return request, metadata @@ -147,6 +156,29 @@ def post_collect_user_event( """ return response + def pre_export_user_events( + self, + request: export_config.ExportUserEventsRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[export_config.ExportUserEventsRequest, Sequence[Tuple[str, str]]]: + """Pre-rpc interceptor for export_user_events + + Override in a subclass to manipulate the request or metadata + before they are sent to the UserEventService server. + """ + return request, metadata + + def post_export_user_events( + self, response: operations_pb2.Operation + ) -> operations_pb2.Operation: + """Post-rpc interceptor for export_user_events + + Override in a subclass to manipulate the response + after it is returned by the UserEventService server but before + it is returned to user code. + """ + return response + def pre_import_user_events( self, request: import_config.ImportUserEventsRequest, @@ -587,6 +619,101 @@ def __call__( resp = self._interceptor.post_collect_user_event(resp) return resp + class _ExportUserEvents(UserEventServiceRestStub): + def __hash__(self): + return hash("ExportUserEvents") + + __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} + + @classmethod + def _get_unset_required_fields(cls, message_dict): + return { + k: v + for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items() + if k not in message_dict + } + + def __call__( + self, + request: export_config.ExportUserEventsRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operations_pb2.Operation: + r"""Call the export user events method over HTTP. + + Args: + request (~.export_config.ExportUserEventsRequest): + The request object. Request message for the ``ExportUserEvents`` method. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + ~.operations_pb2.Operation: + This resource represents a + long-running operation that is the + result of a network API call. + + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "post", + "uri": "/v2alpha/{parent=projects/*/locations/*/catalogs/*}/userEvents:export", + "body": "*", + }, + ] + request, metadata = self._interceptor.pre_export_user_events( + request, metadata + ) + pb_request = export_config.ExportUserEventsRequest.pb(request) + transcoded_request = path_template.transcode(http_options, pb_request) + + # Jsonify the request body + + body = json_format.MessageToJson( + transcoded_request["body"], use_integers_for_enums=True + ) + uri = transcoded_request["uri"] + method = transcoded_request["method"] + + # Jsonify the query params + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + use_integers_for_enums=True, + ) + ) + query_params.update(self._get_unset_required_fields(query_params)) + + query_params["$alt"] = "json;enum-encoding=int" + + # Send the request + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(self._session, method)( + "{host}{uri}".format(host=self._host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + data=body, + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + # Return the response + resp = operations_pb2.Operation() + json_format.Parse(response.content, resp, ignore_unknown_fields=True) + resp = self._interceptor.post_export_user_events(resp) + return resp + class _ImportUserEvents(UserEventServiceRestStub): def __hash__(self): return hash("ImportUserEvents") @@ -982,6 +1109,14 @@ def collect_user_event( # In C++ this would require a dynamic_cast return self._CollectUserEvent(self._session, self._host, self._interceptor) # type: ignore + @property + def export_user_events( + self, + ) -> Callable[[export_config.ExportUserEventsRequest], operations_pb2.Operation]: + # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here. + # In C++ this would require a dynamic_cast + return self._ExportUserEvents(self._session, self._host, self._interceptor) # type: ignore + @property def import_user_events( self, diff --git a/packages/google-cloud-retail/google/cloud/retail_v2alpha/types/__init__.py b/packages/google-cloud-retail/google/cloud/retail_v2alpha/types/__init__.py index 8e2838eb82f6..b65a9c369e9d 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2alpha/types/__init__.py +++ b/packages/google-cloud-retail/google/cloud/retail_v2alpha/types/__init__.py @@ -76,12 +76,27 @@ ExportAnalyticsMetricsResponse, ExportErrorsConfig, ExportMetadata, + ExportProductsRequest, ExportProductsResponse, + ExportUserEventsRequest, ExportUserEventsResponse, GcsOutputResult, OutputConfig, OutputResult, ) +from .generative_question import ( + GenerativeQuestionConfig, + GenerativeQuestionsFeatureConfig, +) +from .generative_question_service import ( + BatchUpdateGenerativeQuestionConfigsRequest, + BatchUpdateGenerativeQuestionConfigsResponse, + GetGenerativeQuestionsFeatureConfigRequest, + ListGenerativeQuestionConfigsRequest, + ListGenerativeQuestionConfigsResponse, + UpdateGenerativeQuestionConfigRequest, + UpdateGenerativeQuestionsFeatureConfigRequest, +) from .import_config import ( BigQuerySource, CompletionDataInputConfig, @@ -174,7 +189,14 @@ PurgeUserEventsRequest, PurgeUserEventsResponse, ) -from .search_service import ExperimentInfo, SearchRequest, SearchResponse +from .search_service import ( + ExperimentInfo, + ProductAttributeInterval, + ProductAttributeValue, + SearchRequest, + SearchResponse, + Tile, +) from .serving_config import ServingConfig from .serving_config_service import ( AddControlRequest, @@ -254,11 +276,22 @@ "ExportAnalyticsMetricsResponse", "ExportErrorsConfig", "ExportMetadata", + "ExportProductsRequest", "ExportProductsResponse", + "ExportUserEventsRequest", "ExportUserEventsResponse", "GcsOutputResult", "OutputConfig", "OutputResult", + "GenerativeQuestionConfig", + "GenerativeQuestionsFeatureConfig", + "BatchUpdateGenerativeQuestionConfigsRequest", + "BatchUpdateGenerativeQuestionConfigsResponse", + "GetGenerativeQuestionsFeatureConfigRequest", + "ListGenerativeQuestionConfigsRequest", + "ListGenerativeQuestionConfigsResponse", + "UpdateGenerativeQuestionConfigRequest", + "UpdateGenerativeQuestionsFeatureConfigRequest", "BigQuerySource", "CompletionDataInputConfig", "GcsSource", @@ -341,8 +374,11 @@ "PurgeUserEventsRequest", "PurgeUserEventsResponse", "ExperimentInfo", + "ProductAttributeInterval", + "ProductAttributeValue", "SearchRequest", "SearchResponse", + "Tile", "ServingConfig", "AddControlRequest", "CreateServingConfigRequest", diff --git a/packages/google-cloud-retail/google/cloud/retail_v2alpha/types/branch.py b/packages/google-cloud-retail/google/cloud/retail_v2alpha/types/branch.py index 18bc4a6a677f..a4b0678c3f12 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2alpha/types/branch.py +++ b/packages/google-cloud-retail/google/cloud/retail_v2alpha/types/branch.py @@ -54,7 +54,7 @@ class BranchView(proto.Enum): class Branch(proto.Message): - r"""A data branch that stores + r"""A data branch that stores all instances of [Product][google.cloud.retail.v2alpha.Product]s. Attributes: diff --git a/packages/google-cloud-retail/google/cloud/retail_v2alpha/types/common.py b/packages/google-cloud-retail/google/cloud/retail_v2alpha/types/common.py index 5ef0e4c47aac..21b6e35eec2e 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2alpha/types/common.py +++ b/packages/google-cloud-retail/google/cloud/retail_v2alpha/types/common.py @@ -544,7 +544,7 @@ class ForceReturnFacetAction(proto.Message): facet_position_adjustments (MutableSequence[google.cloud.retail_v2alpha.types.Rule.ForceReturnFacetAction.FacetPositionAdjustment]): Each instance corresponds to a force return attribute for the given condition. There can't - be more 3 instances here. + be more 15 instances here. """ class FacetPositionAdjustment(proto.Message): diff --git a/packages/google-cloud-retail/google/cloud/retail_v2alpha/types/completion_service.py b/packages/google-cloud-retail/google/cloud/retail_v2alpha/types/completion_service.py index 1db0c4f677b5..68fa37c0437f 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2alpha/types/completion_service.py +++ b/packages/google-cloud-retail/google/cloud/retail_v2alpha/types/completion_service.py @@ -108,9 +108,9 @@ class CompleteQueryRequest(proto.Message): higher, it will be capped by 20. enable_attribute_suggestions (bool): If true, attribute suggestions are enabled - and provided in response. - This field is only available for "cloud-retail" - dataset. + and provided in the response. + This field is only available for the + "cloud-retail" dataset. entity (str): The entity for customers who run multiple entities, domains, sites, or regions, for example, ``Google US``, @@ -277,10 +277,11 @@ class RecentSearchResult(proto.Message): class AttributeResult(proto.Message): r"""Resource that represents attribute results. + The list of suggestions for the attribute. Attributes: suggestions (MutableSequence[str]): - The list of suggestions for the attribute. + """ suggestions: MutableSequence[str] = proto.RepeatedField( diff --git a/packages/google-cloud-retail/google/cloud/retail_v2alpha/types/export_config.py b/packages/google-cloud-retail/google/cloud/retail_v2alpha/types/export_config.py index ad68fdebe29c..ef1044e54f91 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2alpha/types/export_config.py +++ b/packages/google-cloud-retail/google/cloud/retail_v2alpha/types/export_config.py @@ -26,6 +26,8 @@ manifest={ "OutputConfig", "ExportErrorsConfig", + "ExportProductsRequest", + "ExportUserEventsRequest", "ExportAnalyticsMetricsRequest", "ExportMetadata", "ExportProductsResponse", @@ -147,6 +149,145 @@ class ExportErrorsConfig(proto.Message): ) +class ExportProductsRequest(proto.Message): + r"""Request message for ExportProducts method. + + Attributes: + parent (str): + Required. Resource name of a + [Branch][google.cloud.retail.v2alpha.Branch], and + ``default_branch`` for branch_id component is supported. For + example + ``projects/1234/locations/global/catalogs/default_catalog/branches/default_branch`` + output_config (google.cloud.retail_v2alpha.types.OutputConfig): + Required. The output location of the data. + filter (str): + A filtering expression to specify restrictions on returned + events. The expression is a sequence of terms. Each term + applies a restriction to the returned products. Use this + expression to restrict results to a specific time range, + tag, or stock state or to filter products by product type. + For example, + ``lastModifiedTime > "2012-04-23T18:25:43.511Z" lastModifiedTime<"2012-04-23T18:25:43.511Z" productType=primary`` + + We expect only four types of fields: + + :: + + * `lastModifiedTime`: This can be specified twice, once with a + less than operator and once with a greater than operator. The + `lastModifiedTime` restriction should result in one, contiguous, + valid, last-modified, time range. + + * `productType`: Supported values are `primary` and `variant`. The + Boolean operators `OR` and `NOT` are supported if the expression is + enclosed in parentheses and must be separated from the + `productType` values by a space. + + * `availability`: Supported values are `IN_STOCK`, `OUT_OF_STOCK`, + `PREORDER`, and `BACKORDER`. Boolean operators `OR` and `NOT` are + supported if the expression is enclosed in parentheses and must be + separated from the `availability` values by a space. + + * `Tag expressions`: Restricts output to products that match all of the + specified tags. Boolean operators `OR` and `NOT` are supported if the + expression is enclosed in parentheses and the operators are separated + from the tag values by a space. Also supported is '`-"tagA"`', which + is equivalent to '`NOT "tagA"`'. Tag values must be double-quoted, + UTF-8 encoded strings and have a size limit of 1,000 characters. + + Some examples of valid filters expressions: + + - Example 1: + ``lastModifiedTime > "2012-04-23T18:25:43.511Z" lastModifiedTime < "2012-04-23T18:30:43.511Z"`` + - Example 2: + ``lastModifiedTime > "2012-04-23T18:25:43.511Z" productType = "variant"`` + - Example 3: + ``tag=("Red" OR "Blue") tag="New-Arrival" tag=(NOT "promotional") productType = "primary" lastModifiedTime < "2018-04-23T18:30:43.511Z"`` + - Example 4: + ``lastModifiedTime > "2012-04-23T18:25:43.511Z"`` + - Example 5: ``availability = (IN_STOCK OR BACKORDER)`` + """ + + parent: str = proto.Field( + proto.STRING, + number=1, + ) + output_config: "OutputConfig" = proto.Field( + proto.MESSAGE, + number=2, + message="OutputConfig", + ) + filter: str = proto.Field( + proto.STRING, + number=3, + ) + + +class ExportUserEventsRequest(proto.Message): + r"""Request message for the ``ExportUserEvents`` method. + + Attributes: + parent (str): + Required. Resource name of a + [Catalog][google.cloud.retail.v2alpha.Catalog]. For example + ``projects/1234/locations/global/catalogs/default_catalog`` + output_config (google.cloud.retail_v2alpha.types.OutputConfig): + Required. The output location of the data. + filter (str): + A filtering expression to specify restrictions on returned + events. The expression is a sequence of terms. Each term + applies a restriction to the returned user events. Use this + expression to restrict results to a specific time range or + to filter events by eventType. For example, + ``eventTime > "2012-04-23T18:25:43.511Z" eventsMissingCatalogItems eventTime<"2012-04-23T18:25:43.511Z" eventType=search`` + + We expect only three types of fields: + + :: + + * `eventTime`: This can be specified twice, once with a + less than operator and once with a greater than operator. The + `eventTime` restriction should result in one, contiguous, valid, + `eventTime` range. + + * `eventType`: Boolean operators `OR` and `NOT` are supported if the + expression is enclosed in parentheses and the operators are separated + from the tag values by a space. + + * `eventsMissingCatalogItems`: This restricts results + to events for which catalog items were not found in the catalog. The + default behavior is to return only those events for which catalog + items were found. + + Some examples of valid filters expressions: + + - Example 1: + ``eventTime > "2012-04-23T18:25:43.511Z" eventTime < "2012-04-23T18:30:43.511Z"`` + - Example 2: + ``eventTime > "2012-04-23T18:25:43.511Z" eventType = detail-page-view`` + - Example 3: + ``eventsMissingCatalogItems eventType = (NOT search) eventTime < "2018-04-23T18:30:43.511Z"`` + - Example 4: ``eventTime > "2012-04-23T18:25:43.511Z"`` + - Example 5: ``eventType = (detail-page-view OR search)`` + - Example 6: ``eventsMissingCatalogItems`` + """ + + parent: str = proto.Field( + proto.STRING, + number=1, + ) + output_config: "OutputConfig" = proto.Field( + proto.MESSAGE, + number=2, + message="OutputConfig", + ) + filter: str = proto.Field( + proto.STRING, + number=3, + ) + + class ExportAnalyticsMetricsRequest(proto.Message): r"""Request message for the ``ExportAnalyticsMetrics`` method. diff --git a/packages/google-cloud-retail/google/cloud/retail_v2alpha/types/generative_question.py b/packages/google-cloud-retail/google/cloud/retail_v2alpha/types/generative_question.py new file mode 100644 index 000000000000..17809de0fe83 --- /dev/null +++ b/packages/google-cloud-retail/google/cloud/retail_v2alpha/types/generative_question.py @@ -0,0 +1,122 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + +from typing import MutableMapping, MutableSequence + +import proto # type: ignore + +__protobuf__ = proto.module( + package="google.cloud.retail.v2alpha", + manifest={ + "GenerativeQuestionsFeatureConfig", + "GenerativeQuestionConfig", + }, +) + + +class GenerativeQuestionsFeatureConfig(proto.Message): + r"""Configuration for overall generative question feature state. + + Attributes: + catalog (str): + Required. Resource name of the affected + catalog. Format: + projects/{project}/locations/{location}/catalogs/{catalog} + feature_enabled (bool): + Optional. Determines whether questions will + be used at serving time. Note: This feature + cannot be enabled until initial data + requirements are satisfied. + minimum_products (int): + Optional. Minimum number of products in the + response to trigger follow-up questions. Value + must be 0 or positive. + """ + + catalog: str = proto.Field( + proto.STRING, + number=1, + ) + feature_enabled: bool = proto.Field( + proto.BOOL, + number=2, + ) + minimum_products: int = proto.Field( + proto.INT32, + number=3, + ) + + +class GenerativeQuestionConfig(proto.Message): + r"""Configuration for a single generated question. + + Attributes: + catalog (str): + Required. Resource name of the catalog. + Format: + projects/{project}/locations/{location}/catalogs/{catalog} + facet (str): + Required. The facet to which the question is + associated. + generated_question (str): + Output only. The LLM generated question. + final_question (str): + Optional. The question that will be used at serving time. + Question can have a max length of 300 bytes. When not + populated, generated_question should be used. + example_values (MutableSequence[str]): + Output only. Values that can be used to + answer the question. + frequency (float): + Output only. The ratio of how often a + question was asked. + allowed_in_conversation (bool): + Optional. Whether the question is asked at + serving time. + """ + + catalog: str = proto.Field( + proto.STRING, + number=1, + ) + facet: str = proto.Field( + proto.STRING, + number=2, + ) + generated_question: str = proto.Field( + proto.STRING, + number=3, + ) + final_question: str = proto.Field( + proto.STRING, + number=4, + ) + example_values: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=5, + ) + frequency: float = proto.Field( + proto.FLOAT, + number=6, + ) + allowed_in_conversation: bool = proto.Field( + proto.BOOL, + number=7, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/packages/google-cloud-retail/google/cloud/retail_v2alpha/types/generative_question_service.py b/packages/google-cloud-retail/google/cloud/retail_v2alpha/types/generative_question_service.py new file mode 100644 index 000000000000..d888c45b8077 --- /dev/null +++ b/packages/google-cloud-retail/google/cloud/retail_v2alpha/types/generative_question_service.py @@ -0,0 +1,187 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + +from typing import MutableMapping, MutableSequence + +from google.protobuf import field_mask_pb2 # type: ignore +import proto # type: ignore + +from google.cloud.retail_v2alpha.types import generative_question + +__protobuf__ = proto.module( + package="google.cloud.retail.v2alpha", + manifest={ + "UpdateGenerativeQuestionsFeatureConfigRequest", + "GetGenerativeQuestionsFeatureConfigRequest", + "ListGenerativeQuestionConfigsRequest", + "ListGenerativeQuestionConfigsResponse", + "UpdateGenerativeQuestionConfigRequest", + "BatchUpdateGenerativeQuestionConfigsRequest", + "BatchUpdateGenerativeQuestionConfigsResponse", + }, +) + + +class UpdateGenerativeQuestionsFeatureConfigRequest(proto.Message): + r"""Request for UpdateGenerativeQuestionsFeatureConfig method. + + Attributes: + generative_questions_feature_config (google.cloud.retail_v2alpha.types.GenerativeQuestionsFeatureConfig): + Required. The configuration managing the + feature state. + update_mask (google.protobuf.field_mask_pb2.FieldMask): + Optional. Indicates which fields in the provided + [GenerativeQuestionsFeatureConfig][google.cloud.retail.v2alpha.GenerativeQuestionsFeatureConfig] + to update. If not set or empty, all supported fields are + updated. + """ + + generative_questions_feature_config: generative_question.GenerativeQuestionsFeatureConfig = proto.Field( + proto.MESSAGE, + number=2, + message=generative_question.GenerativeQuestionsFeatureConfig, + ) + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=4, + message=field_mask_pb2.FieldMask, + ) + + +class GetGenerativeQuestionsFeatureConfigRequest(proto.Message): + r"""Request for GetGenerativeQuestionsFeatureConfig method. + + Attributes: + catalog (str): + Required. Resource name of the parent + catalog. Format: + projects/{project}/locations/{location}/catalogs/{catalog} + """ + + catalog: str = proto.Field( + proto.STRING, + number=1, + ) + + +class ListGenerativeQuestionConfigsRequest(proto.Message): + r"""Request for ListQuestions method. + + Attributes: + parent (str): + Required. Resource name of the parent + catalog. Format: + projects/{project}/locations/{location}/catalogs/{catalog} + """ + + parent: str = proto.Field( + proto.STRING, + number=1, + ) + + +class ListGenerativeQuestionConfigsResponse(proto.Message): + r"""Response for ListQuestions method. + + Attributes: + generative_question_configs (MutableSequence[google.cloud.retail_v2alpha.types.GenerativeQuestionConfig]): + All the questions for a given catalog. + """ + + generative_question_configs: MutableSequence[ + generative_question.GenerativeQuestionConfig + ] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message=generative_question.GenerativeQuestionConfig, + ) + + +class UpdateGenerativeQuestionConfigRequest(proto.Message): + r"""Request for UpdateGenerativeQuestionConfig method. + + Attributes: + generative_question_config (google.cloud.retail_v2alpha.types.GenerativeQuestionConfig): + Required. The question to update. + update_mask (google.protobuf.field_mask_pb2.FieldMask): + Optional. Indicates which fields in the provided + [GenerativeQuestionConfig][google.cloud.retail.v2alpha.GenerativeQuestionConfig] + to update. The following are NOT supported: + + - [GenerativeQuestionConfig.frequency][google.cloud.retail.v2alpha.GenerativeQuestionConfig.frequency] + + If not set or empty, all supported fields are updated. + """ + + generative_question_config: generative_question.GenerativeQuestionConfig = ( + proto.Field( + proto.MESSAGE, + number=3, + message=generative_question.GenerativeQuestionConfig, + ) + ) + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=4, + message=field_mask_pb2.FieldMask, + ) + + +class BatchUpdateGenerativeQuestionConfigsRequest(proto.Message): + r"""Request for BatchUpdateGenerativeQuestionConfig method. + + Attributes: + parent (str): + Optional. Resource name of the parent + catalog. Format: + projects/{project}/locations/{location}/catalogs/{catalog} + requests (MutableSequence[google.cloud.retail_v2alpha.types.UpdateGenerativeQuestionConfigRequest]): + Required. The updates question configs. + """ + + parent: str = proto.Field( + proto.STRING, + number=1, + ) + requests: MutableSequence[ + "UpdateGenerativeQuestionConfigRequest" + ] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="UpdateGenerativeQuestionConfigRequest", + ) + + +class BatchUpdateGenerativeQuestionConfigsResponse(proto.Message): + r"""Aggregated response for UpdateGenerativeQuestionConfig + method. + + Attributes: + generative_question_configs (MutableSequence[google.cloud.retail_v2alpha.types.GenerativeQuestionConfig]): + Optional. The updates question configs. + """ + + generative_question_configs: MutableSequence[ + generative_question.GenerativeQuestionConfig + ] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message=generative_question.GenerativeQuestionConfig, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/packages/google-cloud-retail/google/cloud/retail_v2alpha/types/model.py b/packages/google-cloud-retail/google/cloud/retail_v2alpha/types/model.py index ccccb18de456..cfe6eec1c550 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2alpha/types/model.py +++ b/packages/google-cloud-retail/google/cloud/retail_v2alpha/types/model.py @@ -565,14 +565,41 @@ class ModelFeaturesConfig(proto.Message): frequently-bought-together models. This field is a member of `oneof`_ ``type_dedicated_config``. + llm_embedding_config (google.cloud.retail_v2alpha.types.Model.ModelFeaturesConfig.LlmEmbeddingConfig): + Optional. LLM embedding config to use for + this model. """ + class LlmEmbeddingConfig(proto.Message): + r"""Config that turns on usage of llm embeddings as features to + the model. Embeddings leverage unstructured text fields like + description and title. + + Attributes: + llm_embedding_version (str): + Optional. The LLM embedding version to use. Currently only + ``v0`` is supported. If not specified, feature will not be + turned on. + """ + + llm_embedding_version: str = proto.Field( + proto.STRING, + number=1, + ) + frequently_bought_together_config: "Model.FrequentlyBoughtTogetherFeaturesConfig" = proto.Field( proto.MESSAGE, number=1, oneof="type_dedicated_config", message="Model.FrequentlyBoughtTogetherFeaturesConfig", ) + llm_embedding_config: "Model.ModelFeaturesConfig.LlmEmbeddingConfig" = ( + proto.Field( + proto.MESSAGE, + number=2, + message="Model.ModelFeaturesConfig.LlmEmbeddingConfig", + ) + ) page_optimization_config: PageOptimizationConfig = proto.Field( proto.MESSAGE, diff --git a/packages/google-cloud-retail/google/cloud/retail_v2alpha/types/product.py b/packages/google-cloud-retail/google/cloud/retail_v2alpha/types/product.py index 605ab0503ede..61f9be9e6c3f 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2alpha/types/product.py +++ b/packages/google-cloud-retail/google/cloud/retail_v2alpha/types/product.py @@ -346,6 +346,16 @@ class Product(proto.Message): [Product][google.cloud.retail.v2alpha.Product]. Default to [Availability.IN_STOCK][google.cloud.retail.v2alpha.Product.Availability.IN_STOCK]. + For primary products with variants set the availability of + the primary as + [Availability.OUT_OF_STOCK][google.cloud.retail.v2alpha.Product.Availability.OUT_OF_STOCK] + and set the true availability at the variant level. This way + the primary product will be considered "in stock" as long as + it has at least one variant in stock. + + For primary products with no variants set the true + availability at the primary level. + Corresponding properties: Google Merchant Center property `availability `__. Schema.org property @@ -535,9 +545,6 @@ class Product(proto.Message): - [name][google.cloud.retail.v2alpha.Product.name] - [color_info][google.cloud.retail.v2alpha.Product.color_info] - The maximum number of paths is 30. Otherwise, an - INVALID_ARGUMENT error is returned. - Note: Returning more fields in [SearchResponse][google.cloud.retail.v2alpha.SearchResponse] can increase response payload size and serving latency. diff --git a/packages/google-cloud-retail/google/cloud/retail_v2alpha/types/project.py b/packages/google-cloud-retail/google/cloud/retail_v2alpha/types/project.py index 0e8eba624573..98aa7675a9c3 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2alpha/types/project.py +++ b/packages/google-cloud-retail/google/cloud/retail_v2alpha/types/project.py @@ -210,7 +210,10 @@ class AlertPolicy(proto.Message): Attributes: alert_group (str): The feature that provides alerting capability. Supported - value is only ``search-data-quality`` for now. + value: + + - ``search-data-quality`` for retail search customers. + - ``conv-data-quality`` for retail conversation customers. enroll_status (google.cloud.retail_v2alpha.types.AlertConfig.AlertPolicy.EnrollStatus): The enrollment status of a customer. recipients (MutableSequence[google.cloud.retail_v2alpha.types.AlertConfig.AlertPolicy.Recipient]): diff --git a/packages/google-cloud-retail/google/cloud/retail_v2alpha/types/search_service.py b/packages/google-cloud-retail/google/cloud/retail_v2alpha/types/search_service.py index f9fc2a076ff0..1765d6595858 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2alpha/types/search_service.py +++ b/packages/google-cloud-retail/google/cloud/retail_v2alpha/types/search_service.py @@ -27,6 +27,9 @@ __protobuf__ = proto.module( package="google.cloud.retail.v2alpha", manifest={ + "ProductAttributeValue", + "ProductAttributeInterval", + "Tile", "SearchRequest", "SearchResponse", "ExperimentInfo", @@ -34,6 +37,93 @@ ) +class ProductAttributeValue(proto.Message): + r"""Product attribute which structured by an attribute name and value. + This structure is used in conversational search filters and answers. + For example, if we have ``name=color`` and ``value=red``, this means + that the color is ``red``. + + Attributes: + name (str): + The attribute name. + value (str): + The attribute value. + """ + + name: str = proto.Field( + proto.STRING, + number=1, + ) + value: str = proto.Field( + proto.STRING, + number=2, + ) + + +class ProductAttributeInterval(proto.Message): + r"""Product attribute name and numeric interval. + + Attributes: + name (str): + The attribute name (e.g. "length") + interval (google.cloud.retail_v2alpha.types.Interval): + The numeric interval (e.g. [10, 20)) + """ + + name: str = proto.Field( + proto.STRING, + number=1, + ) + interval: common.Interval = proto.Field( + proto.MESSAGE, + number=2, + message=common.Interval, + ) + + +class Tile(proto.Message): + r"""This field specifies the tile information including an + attribute key, attribute value. More fields will be added in the + future, eg: product id or product counts, etc. + + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + product_attribute_value (google.cloud.retail_v2alpha.types.ProductAttributeValue): + The product attribute key-value. + + This field is a member of `oneof`_ ``product_attribute``. + product_attribute_interval (google.cloud.retail_v2alpha.types.ProductAttributeInterval): + The product attribute key-numeric interval. + + This field is a member of `oneof`_ ``product_attribute``. + representative_product_id (str): + The representative product id for this tile. + """ + + product_attribute_value: "ProductAttributeValue" = proto.Field( + proto.MESSAGE, + number=1, + oneof="product_attribute", + message="ProductAttributeValue", + ) + product_attribute_interval: "ProductAttributeInterval" = proto.Field( + proto.MESSAGE, + number=2, + oneof="product_attribute", + message="ProductAttributeInterval", + ) + representative_product_id: str = proto.Field( + proto.STRING, + number=3, + ) + + class SearchRequest(proto.Message): r"""Request message for [SearchService.Search][google.cloud.retail.v2alpha.SearchService.Search] @@ -334,6 +424,13 @@ class SearchRequest(proto.Message): matched with [UserEvent.entity][google.cloud.retail.v2alpha.UserEvent.entity] to get search results boosted by entity. + conversational_search_spec (google.cloud.retail_v2alpha.types.SearchRequest.ConversationalSearchSpec): + Optional. This field specifies all + conversational related parameters addition to + traditional retail search. + tile_navigation_spec (google.cloud.retail_v2alpha.types.SearchRequest.TileNavigationSpec): + Optional. This field specifies tile + navigation related parameters. """ class RelevanceThreshold(proto.Enum): @@ -940,6 +1037,135 @@ class Mode(proto.Enum): enum="SearchRequest.SpellCorrectionSpec.Mode", ) + class ConversationalSearchSpec(proto.Message): + r"""This field specifies all conversational related parameters + addition to traditional retail search. + + Attributes: + followup_conversation_requested (bool): + This field specifies whether the customer + would like to do conversational search. If this + field is set to true, conversational related + extra information will be returned from server + side, including follow-up question, answer + options, etc. + conversation_id (str): + This field specifies the conversation id, which maintains + the state of the conversation between client side and server + side. Use the value from the previous + [ConversationalSearchResult.conversation_id][]. For the + initial request, this should be empty. + user_answer (google.cloud.retail_v2alpha.types.SearchRequest.ConversationalSearchSpec.UserAnswer): + This field specifies the current user answer + during the conversational search. This can be + either user selected from suggested answers or + user input plain text. + """ + + class UserAnswer(proto.Message): + r"""This field specifies the current user answer during the + conversational search. This can be either user selected from + suggested answers or user input plain text. + + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + text_answer (str): + This field specifies the incremental input + text from the user during the conversational + search. + + This field is a member of `oneof`_ ``type``. + selected_answer (google.cloud.retail_v2alpha.types.SearchRequest.ConversationalSearchSpec.UserAnswer.SelectedAnswer): + This field specifies the selected attributes during the + conversational search. This should be a subset of + [ConversationalSearchResult.suggested_answers][]. + + This field is a member of `oneof`_ ``type``. + """ + + class SelectedAnswer(proto.Message): + r"""This field specifies the selected answers during the + conversational search. + + Attributes: + product_attribute_values (MutableSequence[google.cloud.retail_v2alpha.types.ProductAttributeValue]): + This field is deprecated and should not be + set. + product_attribute_value (google.cloud.retail_v2alpha.types.ProductAttributeValue): + This field specifies the selected answer + which is a attribute key-value. + """ + + product_attribute_values: MutableSequence[ + "ProductAttributeValue" + ] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="ProductAttributeValue", + ) + product_attribute_value: "ProductAttributeValue" = proto.Field( + proto.MESSAGE, + number=2, + message="ProductAttributeValue", + ) + + text_answer: str = proto.Field( + proto.STRING, + number=1, + oneof="type", + ) + selected_answer: "SearchRequest.ConversationalSearchSpec.UserAnswer.SelectedAnswer" = proto.Field( + proto.MESSAGE, + number=2, + oneof="type", + message="SearchRequest.ConversationalSearchSpec.UserAnswer.SelectedAnswer", + ) + + followup_conversation_requested: bool = proto.Field( + proto.BOOL, + number=1, + ) + conversation_id: str = proto.Field( + proto.STRING, + number=2, + ) + user_answer: "SearchRequest.ConversationalSearchSpec.UserAnswer" = proto.Field( + proto.MESSAGE, + number=3, + message="SearchRequest.ConversationalSearchSpec.UserAnswer", + ) + + class TileNavigationSpec(proto.Message): + r"""This field specifies tile navigation related parameters. + + Attributes: + tile_navigation_requested (bool): + This field specifies whether the customer + would like to request tile navigation. + applied_tiles (MutableSequence[google.cloud.retail_v2alpha.types.Tile]): + This field specifies the tiles which are already clicked in + client side. NOTE: This field is not being used for + filtering search products. Client side should also put all + the applied tiles in + [SearchRequest.filter][google.cloud.retail.v2alpha.SearchRequest.filter]. + """ + + tile_navigation_requested: bool = proto.Field( + proto.BOOL, + number=1, + ) + applied_tiles: MutableSequence["Tile"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="Tile", + ) + placement: str = proto.Field( proto.STRING, number=1, @@ -1043,6 +1269,16 @@ class Mode(proto.Enum): proto.STRING, number=38, ) + conversational_search_spec: ConversationalSearchSpec = proto.Field( + proto.MESSAGE, + number=40, + message=ConversationalSearchSpec, + ) + tile_navigation_spec: TileNavigationSpec = proto.Field( + proto.MESSAGE, + number=41, + message=TileNavigationSpec, + ) class SearchResponse(proto.Message): @@ -1100,6 +1336,14 @@ class SearchResponse(proto.Message): [Experiment][google.cloud.retail.v2alpha.Experiment] associated with this response. Only exists when an experiment is triggered. + conversational_search_result (google.cloud.retail_v2alpha.types.SearchResponse.ConversationalSearchResult): + This field specifies all related information + that is needed on client side for UI rendering + of conversational retail search. + tile_navigation_result (google.cloud.retail_v2alpha.types.SearchResponse.TileNavigationResult): + This field specifies all related information + for tile navigation that will be used in client + side. """ class SearchResult(proto.Message): @@ -1348,6 +1592,126 @@ class QueryExpansionInfo(proto.Message): number=2, ) + class ConversationalSearchResult(proto.Message): + r"""This field specifies all related information that is needed + on client side for UI rendering of conversational retail search. + + Attributes: + conversation_id (str): + Conversation UUID. This field will be stored in client side + storage to maintain the conversation session with server and + will be used for next search request's + [SearchRequest.ConversationalSearchSpec.conversation_id][google.cloud.retail.v2alpha.SearchRequest.ConversationalSearchSpec.conversation_id] + to restore conversation state in server. + refined_query (str): + The current refined query for the conversational search. + This field will be used in customer UI that the query in the + search bar should be replaced with the refined query. For + example, if + [SearchRequest.query][google.cloud.retail.v2alpha.SearchRequest.query] + is ``dress`` and next + [SearchRequest.ConversationalSearchSpec.UserAnswer.text_answer][google.cloud.retail.v2alpha.SearchRequest.ConversationalSearchSpec.UserAnswer.text_answer] + is ``red color``, which does not match any product attribute + value filters, the refined query will be + ``dress, red color``. + additional_filters (MutableSequence[google.cloud.retail_v2alpha.types.SearchResponse.ConversationalSearchResult.AdditionalFilter]): + This field is deprecated but will be kept for backward + compatibility. There is expected to have only one additional + filter and the value will be the same to the same as field + ``additional_filter``. + followup_question (str): + The follow-up question. e.g., ``What is the color?`` + suggested_answers (MutableSequence[google.cloud.retail_v2alpha.types.SearchResponse.ConversationalSearchResult.SuggestedAnswer]): + The answer options provided to client for the + follow-up question. + additional_filter (google.cloud.retail_v2alpha.types.SearchResponse.ConversationalSearchResult.AdditionalFilter): + This is the incremental additional filters implied from the + current user answer. User should add the suggested addition + filters to the previous + [SearchRequest.filter][google.cloud.retail.v2alpha.SearchRequest.filter], + and use the merged filter in the follow up search request. + """ + + class SuggestedAnswer(proto.Message): + r"""Suggested answers to the follow-up question. + + Attributes: + product_attribute_value (google.cloud.retail_v2alpha.types.ProductAttributeValue): + Product attribute value, including an + attribute key and an attribute value. Other + types can be added here in the future. + """ + + product_attribute_value: "ProductAttributeValue" = proto.Field( + proto.MESSAGE, + number=1, + message="ProductAttributeValue", + ) + + class AdditionalFilter(proto.Message): + r"""Additional filter that client side need to apply. + + Attributes: + product_attribute_value (google.cloud.retail_v2alpha.types.ProductAttributeValue): + Product attribute value, including an + attribute key and an attribute value. Other + types can be added here in the future. + """ + + product_attribute_value: "ProductAttributeValue" = proto.Field( + proto.MESSAGE, + number=1, + message="ProductAttributeValue", + ) + + conversation_id: str = proto.Field( + proto.STRING, + number=1, + ) + refined_query: str = proto.Field( + proto.STRING, + number=2, + ) + additional_filters: MutableSequence[ + "SearchResponse.ConversationalSearchResult.AdditionalFilter" + ] = proto.RepeatedField( + proto.MESSAGE, + number=3, + message="SearchResponse.ConversationalSearchResult.AdditionalFilter", + ) + followup_question: str = proto.Field( + proto.STRING, + number=4, + ) + suggested_answers: MutableSequence[ + "SearchResponse.ConversationalSearchResult.SuggestedAnswer" + ] = proto.RepeatedField( + proto.MESSAGE, + number=5, + message="SearchResponse.ConversationalSearchResult.SuggestedAnswer", + ) + additional_filter: "SearchResponse.ConversationalSearchResult.AdditionalFilter" = proto.Field( + proto.MESSAGE, + number=6, + message="SearchResponse.ConversationalSearchResult.AdditionalFilter", + ) + + class TileNavigationResult(proto.Message): + r"""This field specifies all related information for tile + navigation that will be used in client side. + + Attributes: + tiles (MutableSequence[google.cloud.retail_v2alpha.types.Tile]): + The current tiles that are used for tile + navigation, sorted by engagement. + """ + + tiles: MutableSequence["Tile"] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="Tile", + ) + @property def raw_page(self): return self @@ -1403,6 +1767,16 @@ def raw_page(self): number=17, message="ExperimentInfo", ) + conversational_search_result: ConversationalSearchResult = proto.Field( + proto.MESSAGE, + number=18, + message=ConversationalSearchResult, + ) + tile_navigation_result: TileNavigationResult = proto.Field( + proto.MESSAGE, + number=19, + message=TileNavigationResult, + ) class ExperimentInfo(proto.Message): diff --git a/packages/google-cloud-retail/google/cloud/retail_v2beta/__init__.py b/packages/google-cloud-retail/google/cloud/retail_v2beta/__init__.py index ce478497840c..c5796d154c8f 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2beta/__init__.py +++ b/packages/google-cloud-retail/google/cloud/retail_v2beta/__init__.py @@ -28,12 +28,17 @@ CompletionServiceClient, ) from .services.control_service import ControlServiceAsyncClient, ControlServiceClient +from .services.generative_question_service import ( + GenerativeQuestionServiceAsyncClient, + GenerativeQuestionServiceClient, +) from .services.model_service import ModelServiceAsyncClient, ModelServiceClient from .services.prediction_service import ( PredictionServiceAsyncClient, PredictionServiceClient, ) from .services.product_service import ProductServiceAsyncClient, ProductServiceClient +from .services.project_service import ProjectServiceAsyncClient, ProjectServiceClient from .services.search_service import SearchServiceAsyncClient, SearchServiceClient from .services.serving_config_service import ( ServingConfigServiceAsyncClient, @@ -104,12 +109,27 @@ ExportAnalyticsMetricsResponse, ExportErrorsConfig, ExportMetadata, + ExportProductsRequest, ExportProductsResponse, + ExportUserEventsRequest, ExportUserEventsResponse, GcsOutputResult, OutputConfig, OutputResult, ) +from .types.generative_question import ( + GenerativeQuestionConfig, + GenerativeQuestionsFeatureConfig, +) +from .types.generative_question_service import ( + BatchUpdateGenerativeQuestionConfigsRequest, + BatchUpdateGenerativeQuestionConfigsResponse, + GetGenerativeQuestionsFeatureConfigRequest, + ListGenerativeQuestionConfigsRequest, + ListGenerativeQuestionConfigsResponse, + UpdateGenerativeQuestionConfigRequest, + UpdateGenerativeQuestionsFeatureConfigRequest, +) from .types.import_config import ( BigQuerySource, CompletionDataInputConfig, @@ -168,6 +188,8 @@ SetInventoryResponse, UpdateProductRequest, ) +from .types.project import AlertConfig +from .types.project_service import GetAlertConfigRequest, UpdateAlertConfigRequest from .types.promotion import Promotion from .types.purge_config import ( PurgeMetadata, @@ -177,7 +199,14 @@ PurgeUserEventsRequest, PurgeUserEventsResponse, ) -from .types.search_service import ExperimentInfo, SearchRequest, SearchResponse +from .types.search_service import ( + ExperimentInfo, + ProductAttributeInterval, + ProductAttributeValue, + SearchRequest, + SearchResponse, + Tile, +) from .types.serving_config import ServingConfig from .types.serving_config_service import ( AddControlRequest, @@ -208,9 +237,11 @@ "CatalogServiceAsyncClient", "CompletionServiceAsyncClient", "ControlServiceAsyncClient", + "GenerativeQuestionServiceAsyncClient", "ModelServiceAsyncClient", "PredictionServiceAsyncClient", "ProductServiceAsyncClient", + "ProjectServiceAsyncClient", "SearchServiceAsyncClient", "ServingConfigServiceAsyncClient", "UserEventServiceAsyncClient", @@ -222,12 +253,15 @@ "AddLocalInventoriesMetadata", "AddLocalInventoriesRequest", "AddLocalInventoriesResponse", + "AlertConfig", "AnalyticsServiceClient", "AttributeConfigLevel", "AttributesConfig", "Audience", "BatchRemoveCatalogAttributesRequest", "BatchRemoveCatalogAttributesResponse", + "BatchUpdateGenerativeQuestionConfigsRequest", + "BatchUpdateGenerativeQuestionConfigsResponse", "BigQueryOutputResult", "BigQuerySource", "Catalog", @@ -259,16 +293,23 @@ "ExportAnalyticsMetricsResponse", "ExportErrorsConfig", "ExportMetadata", + "ExportProductsRequest", "ExportProductsResponse", + "ExportUserEventsRequest", "ExportUserEventsResponse", "FulfillmentInfo", "GcsOutputResult", "GcsSource", + "GenerativeQuestionConfig", + "GenerativeQuestionServiceClient", + "GenerativeQuestionsFeatureConfig", + "GetAlertConfigRequest", "GetAttributesConfigRequest", "GetCompletionConfigRequest", "GetControlRequest", "GetDefaultBranchRequest", "GetDefaultBranchResponse", + "GetGenerativeQuestionsFeatureConfigRequest", "GetModelRequest", "GetProductRequest", "GetServingConfigRequest", @@ -286,6 +327,8 @@ "ListCatalogsResponse", "ListControlsRequest", "ListControlsResponse", + "ListGenerativeQuestionConfigsRequest", + "ListGenerativeQuestionConfigsResponse", "ListModelsRequest", "ListModelsResponse", "ListProductsRequest", @@ -306,11 +349,14 @@ "PredictionServiceClient", "PriceInfo", "Product", + "ProductAttributeInterval", + "ProductAttributeValue", "ProductDetail", "ProductInlineSource", "ProductInputConfig", "ProductLevelConfig", "ProductServiceClient", + "ProjectServiceClient", "Promotion", "PurchaseTransaction", "PurgeMetadata", @@ -346,13 +392,17 @@ "SetInventoryRequest", "SetInventoryResponse", "SolutionType", + "Tile", "TuneModelMetadata", "TuneModelRequest", "TuneModelResponse", + "UpdateAlertConfigRequest", "UpdateAttributesConfigRequest", "UpdateCatalogRequest", "UpdateCompletionConfigRequest", "UpdateControlRequest", + "UpdateGenerativeQuestionConfigRequest", + "UpdateGenerativeQuestionsFeatureConfigRequest", "UpdateModelRequest", "UpdateProductRequest", "UpdateServingConfigRequest", diff --git a/packages/google-cloud-retail/google/cloud/retail_v2beta/gapic_metadata.json b/packages/google-cloud-retail/google/cloud/retail_v2beta/gapic_metadata.json index 8e2a46be9ba2..41f3561de296 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2beta/gapic_metadata.json +++ b/packages/google-cloud-retail/google/cloud/retail_v2beta/gapic_metadata.json @@ -381,6 +381,100 @@ } } }, + "GenerativeQuestionService": { + "clients": { + "grpc": { + "libraryClient": "GenerativeQuestionServiceClient", + "rpcs": { + "BatchUpdateGenerativeQuestionConfigs": { + "methods": [ + "batch_update_generative_question_configs" + ] + }, + "GetGenerativeQuestionsFeatureConfig": { + "methods": [ + "get_generative_questions_feature_config" + ] + }, + "ListGenerativeQuestionConfigs": { + "methods": [ + "list_generative_question_configs" + ] + }, + "UpdateGenerativeQuestionConfig": { + "methods": [ + "update_generative_question_config" + ] + }, + "UpdateGenerativeQuestionsFeatureConfig": { + "methods": [ + "update_generative_questions_feature_config" + ] + } + } + }, + "grpc-async": { + "libraryClient": "GenerativeQuestionServiceAsyncClient", + "rpcs": { + "BatchUpdateGenerativeQuestionConfigs": { + "methods": [ + "batch_update_generative_question_configs" + ] + }, + "GetGenerativeQuestionsFeatureConfig": { + "methods": [ + "get_generative_questions_feature_config" + ] + }, + "ListGenerativeQuestionConfigs": { + "methods": [ + "list_generative_question_configs" + ] + }, + "UpdateGenerativeQuestionConfig": { + "methods": [ + "update_generative_question_config" + ] + }, + "UpdateGenerativeQuestionsFeatureConfig": { + "methods": [ + "update_generative_questions_feature_config" + ] + } + } + }, + "rest": { + "libraryClient": "GenerativeQuestionServiceClient", + "rpcs": { + "BatchUpdateGenerativeQuestionConfigs": { + "methods": [ + "batch_update_generative_question_configs" + ] + }, + "GetGenerativeQuestionsFeatureConfig": { + "methods": [ + "get_generative_questions_feature_config" + ] + }, + "ListGenerativeQuestionConfigs": { + "methods": [ + "list_generative_question_configs" + ] + }, + "UpdateGenerativeQuestionConfig": { + "methods": [ + "update_generative_question_config" + ] + }, + "UpdateGenerativeQuestionsFeatureConfig": { + "methods": [ + "update_generative_questions_feature_config" + ] + } + } + } + } + }, "ModelService": { "clients": { "grpc": { @@ -579,6 +673,11 @@ "delete_product" ] }, + "ExportProducts": { + "methods": [ + "export_products" + ] + }, "GetProduct": { "methods": [ "get_product" @@ -644,6 +743,11 @@ "delete_product" ] }, + "ExportProducts": { + "methods": [ + "export_products" + ] + }, "GetProduct": { "methods": [ "get_product" @@ -709,6 +813,11 @@ "delete_product" ] }, + "ExportProducts": { + "methods": [ + "export_products" + ] + }, "GetProduct": { "methods": [ "get_product" @@ -753,6 +862,55 @@ } } }, + "ProjectService": { + "clients": { + "grpc": { + "libraryClient": "ProjectServiceClient", + "rpcs": { + "GetAlertConfig": { + "methods": [ + "get_alert_config" + ] + }, + "UpdateAlertConfig": { + "methods": [ + "update_alert_config" + ] + } + } + }, + "grpc-async": { + "libraryClient": "ProjectServiceAsyncClient", + "rpcs": { + "GetAlertConfig": { + "methods": [ + "get_alert_config" + ] + }, + "UpdateAlertConfig": { + "methods": [ + "update_alert_config" + ] + } + } + }, + "rest": { + "libraryClient": "ProjectServiceClient", + "rpcs": { + "GetAlertConfig": { + "methods": [ + "get_alert_config" + ] + }, + "UpdateAlertConfig": { + "methods": [ + "update_alert_config" + ] + } + } + } + } + }, "SearchService": { "clients": { "grpc": { @@ -921,6 +1079,11 @@ "collect_user_event" ] }, + "ExportUserEvents": { + "methods": [ + "export_user_events" + ] + }, "ImportUserEvents": { "methods": [ "import_user_events" @@ -951,6 +1114,11 @@ "collect_user_event" ] }, + "ExportUserEvents": { + "methods": [ + "export_user_events" + ] + }, "ImportUserEvents": { "methods": [ "import_user_events" @@ -981,6 +1149,11 @@ "collect_user_event" ] }, + "ExportUserEvents": { + "methods": [ + "export_user_events" + ] + }, "ImportUserEvents": { "methods": [ "import_user_events" diff --git a/packages/google-cloud-retail/google/cloud/retail_v2beta/services/generative_question_service/__init__.py b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/generative_question_service/__init__.py new file mode 100644 index 000000000000..f9196ca8080a --- /dev/null +++ b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/generative_question_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from .async_client import GenerativeQuestionServiceAsyncClient +from .client import GenerativeQuestionServiceClient + +__all__ = ( + "GenerativeQuestionServiceClient", + "GenerativeQuestionServiceAsyncClient", +) diff --git a/packages/google-cloud-retail/google/cloud/retail_v2beta/services/generative_question_service/async_client.py b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/generative_question_service/async_client.py new file mode 100644 index 000000000000..1204a43395cc --- /dev/null +++ b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/generative_question_service/async_client.py @@ -0,0 +1,1060 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import re +from typing import ( + Callable, + Dict, + Mapping, + MutableMapping, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, +) + +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.api_core.client_options import ClientOptions +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.cloud.retail_v2beta import gapic_version as package_version + +try: + OptionalRetry = Union[retries.AsyncRetry, gapic_v1.method._MethodDefault, None] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.AsyncRetry, object, None] # type: ignore + +from google.cloud.location import locations_pb2 # type: ignore +from google.longrunning import operations_pb2 # type: ignore +from google.protobuf import field_mask_pb2 # type: ignore + +from google.cloud.retail_v2beta.types import ( + generative_question, + generative_question_service, +) + +from .client import GenerativeQuestionServiceClient +from .transports.base import DEFAULT_CLIENT_INFO, GenerativeQuestionServiceTransport +from .transports.grpc_asyncio import GenerativeQuestionServiceGrpcAsyncIOTransport + + +class GenerativeQuestionServiceAsyncClient: + """Service for managing LLM generated questions in search + serving. + """ + + _client: GenerativeQuestionServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = GenerativeQuestionServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = GenerativeQuestionServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + GenerativeQuestionServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = GenerativeQuestionServiceClient._DEFAULT_UNIVERSE + + catalog_path = staticmethod(GenerativeQuestionServiceClient.catalog_path) + parse_catalog_path = staticmethod( + GenerativeQuestionServiceClient.parse_catalog_path + ) + common_billing_account_path = staticmethod( + GenerativeQuestionServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + GenerativeQuestionServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + GenerativeQuestionServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + GenerativeQuestionServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + GenerativeQuestionServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + GenerativeQuestionServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + GenerativeQuestionServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + GenerativeQuestionServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + GenerativeQuestionServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + GenerativeQuestionServiceClient.parse_common_location_path + ) + + @classmethod + def from_service_account_info(cls, info: dict, *args, **kwargs): + """Creates an instance of this client using the provided credentials + info. + + Args: + info (dict): The service account private key info. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + GenerativeQuestionServiceAsyncClient: The constructed client. + """ + return GenerativeQuestionServiceClient.from_service_account_info.__func__(GenerativeQuestionServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + GenerativeQuestionServiceAsyncClient: The constructed client. + """ + return GenerativeQuestionServiceClient.from_service_account_file.__func__(GenerativeQuestionServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return GenerativeQuestionServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> GenerativeQuestionServiceTransport: + """Returns the transport used by the client instance. + + Returns: + GenerativeQuestionServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = GenerativeQuestionServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + GenerativeQuestionServiceTransport, + Callable[..., GenerativeQuestionServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the generative question service async client. + + Args: + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + transport (Optional[Union[str,GenerativeQuestionServiceTransport,Callable[..., GenerativeQuestionServiceTransport]]]): + The transport to use, or a Callable that constructs and returns a new transport to use. + If a Callable is given, it will be called with the same set of initialization + arguments as used in the GenerativeQuestionServiceTransport constructor. + If set to None, a transport is chosen automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): + Custom options for the client. + + 1. The ``api_endpoint`` property can be used to override the + default endpoint provided by the client when ``transport`` is + not explicitly provided. Only if this property is not set and + ``transport`` was not explicitly provided, the endpoint is + determined by the GOOGLE_API_USE_MTLS_ENDPOINT environment + variable, which have one of the following values: + "always" (always use the default mTLS endpoint), "never" (always + use the default regular endpoint) and "auto" (auto-switch to the + default mTLS endpoint if client certificate is present; this is + the default value). + + 2. If the GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide a client certificate for mTLS transport. If + not provided, the default SSL client certificate will be used if + present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not + set, no client certificate will be used. + + 3. The ``universe_domain`` property can be used to override the + default "googleapis.com" universe. Note that ``api_endpoint`` + property still takes precedence; and ``universe_domain`` is + currently not supported for mTLS. + + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + + Raises: + google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport + creation failed for any reason. + """ + self._client = GenerativeQuestionServiceClient( + credentials=credentials, + transport=transport, + client_options=client_options, + client_info=client_info, + ) + + async def update_generative_questions_feature_config( + self, + request: Optional[ + Union[ + generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest, + dict, + ] + ] = None, + *, + generative_questions_feature_config: Optional[ + generative_question.GenerativeQuestionsFeatureConfig + ] = None, + update_mask: Optional[field_mask_pb2.FieldMask] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> generative_question.GenerativeQuestionsFeatureConfig: + r"""Manages overal generative question feature state -- + enables toggling feature on and off. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import retail_v2beta + + async def sample_update_generative_questions_feature_config(): + # Create a client + client = retail_v2beta.GenerativeQuestionServiceAsyncClient() + + # Initialize request argument(s) + generative_questions_feature_config = retail_v2beta.GenerativeQuestionsFeatureConfig() + generative_questions_feature_config.catalog = "catalog_value" + + request = retail_v2beta.UpdateGenerativeQuestionsFeatureConfigRequest( + generative_questions_feature_config=generative_questions_feature_config, + ) + + # Make the request + response = await client.update_generative_questions_feature_config(request=request) + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.retail_v2beta.types.UpdateGenerativeQuestionsFeatureConfigRequest, dict]]): + The request object. Request for + UpdateGenerativeQuestionsFeatureConfig + method. + generative_questions_feature_config (:class:`google.cloud.retail_v2beta.types.GenerativeQuestionsFeatureConfig`): + Required. The configuration managing + the feature state. + + This corresponds to the ``generative_questions_feature_config`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + update_mask (:class:`google.protobuf.field_mask_pb2.FieldMask`): + Optional. Indicates which fields in the provided + [GenerativeQuestionsFeatureConfig][google.cloud.retail.v2beta.GenerativeQuestionsFeatureConfig] + to update. If not set or empty, all supported fields are + updated. + + This corresponds to the ``update_mask`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry_async.AsyncRetry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.retail_v2beta.types.GenerativeQuestionsFeatureConfig: + Configuration for overall generative + question feature state. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([generative_questions_feature_config, update_mask]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance( + request, + generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest, + ): + request = generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if generative_questions_feature_config is not None: + request.generative_questions_feature_config = ( + generative_questions_feature_config + ) + if update_mask is not None: + request.update_mask = update_mask + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.update_generative_questions_feature_config + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + ( + ( + "generative_questions_feature_config.catalog", + request.generative_questions_feature_config.catalog, + ), + ) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def get_generative_questions_feature_config( + self, + request: Optional[ + Union[ + generative_question_service.GetGenerativeQuestionsFeatureConfigRequest, + dict, + ] + ] = None, + *, + catalog: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> generative_question.GenerativeQuestionsFeatureConfig: + r"""Manages overal generative question feature state -- + enables toggling feature on and off. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import retail_v2beta + + async def sample_get_generative_questions_feature_config(): + # Create a client + client = retail_v2beta.GenerativeQuestionServiceAsyncClient() + + # Initialize request argument(s) + request = retail_v2beta.GetGenerativeQuestionsFeatureConfigRequest( + catalog="catalog_value", + ) + + # Make the request + response = await client.get_generative_questions_feature_config(request=request) + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.retail_v2beta.types.GetGenerativeQuestionsFeatureConfigRequest, dict]]): + The request object. Request for + GetGenerativeQuestionsFeatureConfig + method. + catalog (:class:`str`): + Required. Resource name of the parent + catalog. Format: + projects/{project}/locations/{location}/catalogs/{catalog} + + This corresponds to the ``catalog`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry_async.AsyncRetry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.retail_v2beta.types.GenerativeQuestionsFeatureConfig: + Configuration for overall generative + question feature state. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([catalog]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance( + request, + generative_question_service.GetGenerativeQuestionsFeatureConfigRequest, + ): + request = ( + generative_question_service.GetGenerativeQuestionsFeatureConfigRequest( + request + ) + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if catalog is not None: + request.catalog = catalog + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.get_generative_questions_feature_config + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("catalog", request.catalog),)), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def list_generative_question_configs( + self, + request: Optional[ + Union[ + generative_question_service.ListGenerativeQuestionConfigsRequest, dict + ] + ] = None, + *, + parent: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> generative_question_service.ListGenerativeQuestionConfigsResponse: + r"""Returns all questions for a given catalog. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import retail_v2beta + + async def sample_list_generative_question_configs(): + # Create a client + client = retail_v2beta.GenerativeQuestionServiceAsyncClient() + + # Initialize request argument(s) + request = retail_v2beta.ListGenerativeQuestionConfigsRequest( + parent="parent_value", + ) + + # Make the request + response = await client.list_generative_question_configs(request=request) + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.retail_v2beta.types.ListGenerativeQuestionConfigsRequest, dict]]): + The request object. Request for ListQuestions method. + parent (:class:`str`): + Required. Resource name of the parent + catalog. Format: + projects/{project}/locations/{location}/catalogs/{catalog} + + This corresponds to the ``parent`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry_async.AsyncRetry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.retail_v2beta.types.ListGenerativeQuestionConfigsResponse: + Response for ListQuestions method. + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([parent]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance( + request, generative_question_service.ListGenerativeQuestionConfigsRequest + ): + request = generative_question_service.ListGenerativeQuestionConfigsRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if parent is not None: + request.parent = parent + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.list_generative_question_configs + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def update_generative_question_config( + self, + request: Optional[ + Union[ + generative_question_service.UpdateGenerativeQuestionConfigRequest, dict + ] + ] = None, + *, + generative_question_config: Optional[ + generative_question.GenerativeQuestionConfig + ] = None, + update_mask: Optional[field_mask_pb2.FieldMask] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> generative_question.GenerativeQuestionConfig: + r"""Allows management of individual questions. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import retail_v2beta + + async def sample_update_generative_question_config(): + # Create a client + client = retail_v2beta.GenerativeQuestionServiceAsyncClient() + + # Initialize request argument(s) + generative_question_config = retail_v2beta.GenerativeQuestionConfig() + generative_question_config.catalog = "catalog_value" + generative_question_config.facet = "facet_value" + + request = retail_v2beta.UpdateGenerativeQuestionConfigRequest( + generative_question_config=generative_question_config, + ) + + # Make the request + response = await client.update_generative_question_config(request=request) + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.retail_v2beta.types.UpdateGenerativeQuestionConfigRequest, dict]]): + The request object. Request for + UpdateGenerativeQuestionConfig method. + generative_question_config (:class:`google.cloud.retail_v2beta.types.GenerativeQuestionConfig`): + Required. The question to update. + This corresponds to the ``generative_question_config`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + update_mask (:class:`google.protobuf.field_mask_pb2.FieldMask`): + Optional. Indicates which fields in the provided + [GenerativeQuestionConfig][google.cloud.retail.v2beta.GenerativeQuestionConfig] + to update. The following are NOT supported: + + - [GenerativeQuestionConfig.frequency][google.cloud.retail.v2beta.GenerativeQuestionConfig.frequency] + + If not set or empty, all supported fields are updated. + + This corresponds to the ``update_mask`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry_async.AsyncRetry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.retail_v2beta.types.GenerativeQuestionConfig: + Configuration for a single generated + question. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([generative_question_config, update_mask]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance( + request, generative_question_service.UpdateGenerativeQuestionConfigRequest + ): + request = generative_question_service.UpdateGenerativeQuestionConfigRequest( + request + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if generative_question_config is not None: + request.generative_question_config = generative_question_config + if update_mask is not None: + request.update_mask = update_mask + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.update_generative_question_config + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + ( + ( + "generative_question_config.catalog", + request.generative_question_config.catalog, + ), + ) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def batch_update_generative_question_configs( + self, + request: Optional[ + Union[ + generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest, + dict, + ] + ] = None, + *, + parent: Optional[str] = None, + requests: Optional[ + MutableSequence[ + generative_question_service.UpdateGenerativeQuestionConfigRequest + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse: + r"""Allows management of multiple questions. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import retail_v2beta + + async def sample_batch_update_generative_question_configs(): + # Create a client + client = retail_v2beta.GenerativeQuestionServiceAsyncClient() + + # Initialize request argument(s) + requests = retail_v2beta.UpdateGenerativeQuestionConfigRequest() + requests.generative_question_config.catalog = "catalog_value" + requests.generative_question_config.facet = "facet_value" + + request = retail_v2beta.BatchUpdateGenerativeQuestionConfigsRequest( + requests=requests, + ) + + # Make the request + response = await client.batch_update_generative_question_configs(request=request) + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.retail_v2beta.types.BatchUpdateGenerativeQuestionConfigsRequest, dict]]): + The request object. Request for + BatchUpdateGenerativeQuestionConfig + method. + parent (:class:`str`): + Optional. Resource name of the parent + catalog. Format: + projects/{project}/locations/{location}/catalogs/{catalog} + + This corresponds to the ``parent`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + requests (:class:`MutableSequence[google.cloud.retail_v2beta.types.UpdateGenerativeQuestionConfigRequest]`): + Required. The updates question + configs. + + This corresponds to the ``requests`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry_async.AsyncRetry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.retail_v2beta.types.BatchUpdateGenerativeQuestionConfigsResponse: + Aggregated response for + UpdateGenerativeQuestionConfig method. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([parent, requests]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance( + request, + generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest, + ): + request = ( + generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest( + request + ) + ) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if parent is not None: + request.parent = parent + if requests: + request.requests.extend(requests) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.batch_update_generative_question_configs + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def list_operations( + self, + request: Optional[operations_pb2.ListOperationsRequest] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operations_pb2.ListOperationsResponse: + r"""Lists operations that match the specified filter in the request. + + Args: + request (:class:`~.operations_pb2.ListOperationsRequest`): + The request object. Request message for + `ListOperations` method. + retry (google.api_core.retry_async.AsyncRetry): Designation of what errors, + if any, should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + Returns: + ~.operations_pb2.ListOperationsResponse: + Response message for ``ListOperations`` method. + """ + # Create or coerce a protobuf request object. + # The request isn't a proto-plus wrapped type, + # so it must be constructed via keyword expansion. + if isinstance(request, dict): + request = operations_pb2.ListOperationsRequest(**request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method_async.wrap_method( + self._client._transport.list_operations, + default_timeout=None, + client_info=DEFAULT_CLIENT_INFO, + ) + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def get_operation( + self, + request: Optional[operations_pb2.GetOperationRequest] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operations_pb2.Operation: + r"""Gets the latest state of a long-running operation. + + Args: + request (:class:`~.operations_pb2.GetOperationRequest`): + The request object. Request message for + `GetOperation` method. + retry (google.api_core.retry_async.AsyncRetry): Designation of what errors, + if any, should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + Returns: + ~.operations_pb2.Operation: + An ``Operation`` object. + """ + # Create or coerce a protobuf request object. + # The request isn't a proto-plus wrapped type, + # so it must be constructed via keyword expansion. + if isinstance(request, dict): + request = operations_pb2.GetOperationRequest(**request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method_async.wrap_method( + self._client._transport.get_operation, + default_timeout=None, + client_info=DEFAULT_CLIENT_INFO, + ) + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "GenerativeQuestionServiceAsyncClient": + return self + + async def __aexit__(self, exc_type, exc, tb): + await self.transport.close() + + +DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=package_version.__version__ +) + + +__all__ = ("GenerativeQuestionServiceAsyncClient",) diff --git a/packages/google-cloud-retail/google/cloud/retail_v2beta/services/generative_question_service/client.py b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/generative_question_service/client.py new file mode 100644 index 000000000000..c8d7b019c8ea --- /dev/null +++ b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/generative_question_service/client.py @@ -0,0 +1,1480 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Callable, + Dict, + Mapping, + MutableMapping, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.cloud.retail_v2beta import gapic_version as package_version + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault, None] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object, None] # type: ignore + +from google.cloud.location import locations_pb2 # type: ignore +from google.longrunning import operations_pb2 # type: ignore +from google.protobuf import field_mask_pb2 # type: ignore + +from google.cloud.retail_v2beta.types import ( + generative_question, + generative_question_service, +) + +from .transports.base import DEFAULT_CLIENT_INFO, GenerativeQuestionServiceTransport +from .transports.grpc import GenerativeQuestionServiceGrpcTransport +from .transports.grpc_asyncio import GenerativeQuestionServiceGrpcAsyncIOTransport +from .transports.rest import GenerativeQuestionServiceRestTransport + + +class GenerativeQuestionServiceClientMeta(type): + """Metaclass for the GenerativeQuestionService client. + + This provides class-level methods for building and retrieving + support objects (e.g. transport) without polluting the client instance + objects. + """ + + _transport_registry = ( + OrderedDict() + ) # type: Dict[str, Type[GenerativeQuestionServiceTransport]] + _transport_registry["grpc"] = GenerativeQuestionServiceGrpcTransport + _transport_registry["grpc_asyncio"] = GenerativeQuestionServiceGrpcAsyncIOTransport + _transport_registry["rest"] = GenerativeQuestionServiceRestTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[GenerativeQuestionServiceTransport]: + """Returns an appropriate transport class. + + Args: + label: The name of the desired transport. If none is + provided, then the first transport in the registry is used. + + Returns: + The transport class to use. + """ + # If a specific transport is requested, return that one. + if label: + return cls._transport_registry[label] + + # No transport is requested; return the default (that is, the first one + # in the dictionary). + return next(iter(cls._transport_registry.values())) + + +class GenerativeQuestionServiceClient(metaclass=GenerativeQuestionServiceClientMeta): + """Service for managing LLM generated questions in search + serving. + """ + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "retail.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "retail.{UNIVERSE_DOMAIN}" + _DEFAULT_UNIVERSE = "googleapis.com" + + @classmethod + def from_service_account_info(cls, info: dict, *args, **kwargs): + """Creates an instance of this client using the provided credentials + info. + + Args: + info (dict): The service account private key info. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + GenerativeQuestionServiceClient: The constructed client. + """ + credentials = service_account.Credentials.from_service_account_info(info) + kwargs["credentials"] = credentials + return cls(*args, **kwargs) + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + GenerativeQuestionServiceClient: The constructed client. + """ + credentials = service_account.Credentials.from_service_account_file(filename) + kwargs["credentials"] = credentials + return cls(*args, **kwargs) + + from_service_account_json = from_service_account_file + + @property + def transport(self) -> GenerativeQuestionServiceTransport: + """Returns the transport used by the client instance. + + Returns: + GenerativeQuestionServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def catalog_path( + project: str, + location: str, + catalog: str, + ) -> str: + """Returns a fully-qualified catalog string.""" + return "projects/{project}/locations/{location}/catalogs/{catalog}".format( + project=project, + location=location, + catalog=catalog, + ) + + @staticmethod + def parse_catalog_path(path: str) -> Dict[str, str]: + """Parses a catalog path into its component segments.""" + m = re.match( + r"^projects/(?P.+?)/locations/(?P.+?)/catalogs/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def common_billing_account_path( + billing_account: str, + ) -> str: + """Returns a fully-qualified billing_account string.""" + return "billingAccounts/{billing_account}".format( + billing_account=billing_account, + ) + + @staticmethod + def parse_common_billing_account_path(path: str) -> Dict[str, str]: + """Parse a billing_account path into its component segments.""" + m = re.match(r"^billingAccounts/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_folder_path( + folder: str, + ) -> str: + """Returns a fully-qualified folder string.""" + return "folders/{folder}".format( + folder=folder, + ) + + @staticmethod + def parse_common_folder_path(path: str) -> Dict[str, str]: + """Parse a folder path into its component segments.""" + m = re.match(r"^folders/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_organization_path( + organization: str, + ) -> str: + """Returns a fully-qualified organization string.""" + return "organizations/{organization}".format( + organization=organization, + ) + + @staticmethod + def parse_common_organization_path(path: str) -> Dict[str, str]: + """Parse a organization path into its component segments.""" + m = re.match(r"^organizations/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_project_path( + project: str, + ) -> str: + """Returns a fully-qualified project string.""" + return "projects/{project}".format( + project=project, + ) + + @staticmethod + def parse_common_project_path(path: str) -> Dict[str, str]: + """Parse a project path into its component segments.""" + m = re.match(r"^projects/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_location_path( + project: str, + location: str, + ) -> str: + """Returns a fully-qualified location string.""" + return "projects/{project}/locations/{location}".format( + project=project, + location=location, + ) + + @staticmethod + def parse_common_location_path(path: str) -> Dict[str, str]: + """Parse a location path into its component segments.""" + m = re.match(r"^projects/(?P.+?)/locations/(?P.+?)$", path) + return m.groupdict() if m else {} + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[client_options_lib.ClientOptions] = None + ): + """Deprecated. Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + + warnings.warn( + "get_mtls_endpoint_and_cert_source is deprecated. Use the api_endpoint property instead.", + DeprecationWarning, + ) + if client_options is None: + client_options = client_options_lib.ClientOptions() + use_client_cert = os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") + use_mtls_endpoint = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_client_cert not in ("true", "false"): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + if use_mtls_endpoint not in ("auto", "never", "always"): + raise MutualTLSChannelError( + "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`" + ) + + # Figure out the client cert source to use. + client_cert_source = None + if use_client_cert == "true": + if client_options.client_cert_source: + client_cert_source = client_options.client_cert_source + elif mtls.has_default_client_cert_source(): + client_cert_source = mtls.default_client_cert_source() + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + elif use_mtls_endpoint == "always" or ( + use_mtls_endpoint == "auto" and client_cert_source + ): + api_endpoint = cls.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = cls.DEFAULT_ENDPOINT + + return api_endpoint, client_cert_source + + @staticmethod + def _read_environment_variables(): + """Returns the environment variables used by the client. + + Returns: + Tuple[bool, str, str]: returns the GOOGLE_API_USE_CLIENT_CERTIFICATE, + GOOGLE_API_USE_MTLS_ENDPOINT, and GOOGLE_CLOUD_UNIVERSE_DOMAIN environment variables. + + Raises: + ValueError: If GOOGLE_API_USE_CLIENT_CERTIFICATE is not + any of ["true", "false"]. + google.auth.exceptions.MutualTLSChannelError: If GOOGLE_API_USE_MTLS_ENDPOINT + is not any of ["auto", "never", "always"]. + """ + use_client_cert = os.getenv( + "GOOGLE_API_USE_CLIENT_CERTIFICATE", "false" + ).lower() + use_mtls_endpoint = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto").lower() + universe_domain_env = os.getenv("GOOGLE_CLOUD_UNIVERSE_DOMAIN") + if use_client_cert not in ("true", "false"): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + if use_mtls_endpoint not in ("auto", "never", "always"): + raise MutualTLSChannelError( + "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`" + ) + return use_client_cert == "true", use_mtls_endpoint, universe_domain_env + + @staticmethod + def _get_client_cert_source(provided_cert_source, use_cert_flag): + """Return the client cert source to be used by the client. + + Args: + provided_cert_source (bytes): The client certificate source provided. + use_cert_flag (bool): A flag indicating whether to use the client certificate. + + Returns: + bytes or None: The client cert source to be used by the client. + """ + client_cert_source = None + if use_cert_flag: + if provided_cert_source: + client_cert_source = provided_cert_source + elif mtls.has_default_client_cert_source(): + client_cert_source = mtls.default_client_cert_source() + return client_cert_source + + @staticmethod + def _get_api_endpoint( + api_override, client_cert_source, universe_domain, use_mtls_endpoint + ): + """Return the API endpoint used by the client. + + Args: + api_override (str): The API endpoint override. If specified, this is always + the return value of this function and the other arguments are not used. + client_cert_source (bytes): The client certificate source used by the client. + universe_domain (str): The universe domain used by the client. + use_mtls_endpoint (str): How to use the mTLS endpoint, which depends also on the other parameters. + Possible values are "always", "auto", or "never". + + Returns: + str: The API endpoint to be used by the client. + """ + if api_override is not None: + api_endpoint = api_override + elif use_mtls_endpoint == "always" or ( + use_mtls_endpoint == "auto" and client_cert_source + ): + _default_universe = GenerativeQuestionServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = GenerativeQuestionServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + GenerativeQuestionServiceClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=universe_domain + ) + ) + return api_endpoint + + @staticmethod + def _get_universe_domain( + client_universe_domain: Optional[str], universe_domain_env: Optional[str] + ) -> str: + """Return the universe domain used by the client. + + Args: + client_universe_domain (Optional[str]): The universe domain configured via the client options. + universe_domain_env (Optional[str]): The universe domain configured via the "GOOGLE_CLOUD_UNIVERSE_DOMAIN" environment variable. + + Returns: + str: The universe domain to be used by the client. + + Raises: + ValueError: If the universe domain is an empty string. + """ + universe_domain = GenerativeQuestionServiceClient._DEFAULT_UNIVERSE + if client_universe_domain is not None: + universe_domain = client_universe_domain + elif universe_domain_env is not None: + universe_domain = universe_domain_env + if len(universe_domain.strip()) == 0: + raise ValueError("Universe Domain cannot be an empty string.") + return universe_domain + + @staticmethod + def _compare_universes( + client_universe: str, credentials: ga_credentials.Credentials + ) -> bool: + """Returns True iff the universe domains used by the client and credentials match. + + Args: + client_universe (str): The universe domain configured via the client options. + credentials (ga_credentials.Credentials): The credentials being used in the client. + + Returns: + bool: True iff client_universe matches the universe in credentials. + + Raises: + ValueError: when client_universe does not match the universe in credentials. + """ + + default_universe = GenerativeQuestionServiceClient._DEFAULT_UNIVERSE + credentials_universe = getattr(credentials, "universe_domain", default_universe) + + if client_universe != credentials_universe: + raise ValueError( + "The configured universe domain " + f"({client_universe}) does not match the universe domain " + f"found in the credentials ({credentials_universe}). " + "If you haven't configured the universe domain explicitly, " + f"`{default_universe}` is the default." + ) + return True + + def _validate_universe_domain(self): + """Validates client's and credentials' universe domains are consistent. + + Returns: + bool: True iff the configured universe domain is valid. + + Raises: + ValueError: If the configured universe domain is not valid. + """ + self._is_universe_domain_valid = ( + self._is_universe_domain_valid + or GenerativeQuestionServiceClient._compare_universes( + self.universe_domain, self.transport._credentials + ) + ) + return self._is_universe_domain_valid + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used by the client instance. + """ + return self._universe_domain + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + GenerativeQuestionServiceTransport, + Callable[..., GenerativeQuestionServiceTransport], + ] + ] = None, + client_options: Optional[Union[client_options_lib.ClientOptions, dict]] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the generative question service client. + + Args: + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + transport (Optional[Union[str,GenerativeQuestionServiceTransport,Callable[..., GenerativeQuestionServiceTransport]]]): + The transport to use, or a Callable that constructs and returns a new transport. + If a Callable is given, it will be called with the same set of initialization + arguments as used in the GenerativeQuestionServiceTransport constructor. + If set to None, a transport is chosen automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): + Custom options for the client. + + 1. The ``api_endpoint`` property can be used to override the + default endpoint provided by the client when ``transport`` is + not explicitly provided. Only if this property is not set and + ``transport`` was not explicitly provided, the endpoint is + determined by the GOOGLE_API_USE_MTLS_ENDPOINT environment + variable, which have one of the following values: + "always" (always use the default mTLS endpoint), "never" (always + use the default regular endpoint) and "auto" (auto-switch to the + default mTLS endpoint if client certificate is present; this is + the default value). + + 2. If the GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide a client certificate for mTLS transport. If + not provided, the default SSL client certificate will be used if + present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not + set, no client certificate will be used. + + 3. The ``universe_domain`` property can be used to override the + default "googleapis.com" universe. Note that the ``api_endpoint`` + property still takes precedence; and ``universe_domain`` is + currently not supported for mTLS. + + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + """ + self._client_options = client_options + if isinstance(self._client_options, dict): + self._client_options = client_options_lib.from_dict(self._client_options) + if self._client_options is None: + self._client_options = client_options_lib.ClientOptions() + self._client_options = cast( + client_options_lib.ClientOptions, self._client_options + ) + + universe_domain_opt = getattr(self._client_options, "universe_domain", None) + + ( + self._use_client_cert, + self._use_mtls_endpoint, + self._universe_domain_env, + ) = GenerativeQuestionServiceClient._read_environment_variables() + self._client_cert_source = ( + GenerativeQuestionServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = GenerativeQuestionServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + api_key_value = getattr(self._client_options, "api_key", None) + if api_key_value and credentials: + raise ValueError( + "client_options.api_key and credentials are mutually exclusive" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + transport_provided = isinstance(transport, GenerativeQuestionServiceTransport) + if transport_provided: + # transport is a GenerativeQuestionServiceTransport instance. + if credentials or self._client_options.credentials_file or api_key_value: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if self._client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = cast(GenerativeQuestionServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or GenerativeQuestionServiceClient._get_api_endpoint( + self._client_options.api_endpoint, + self._client_cert_source, + self._universe_domain, + self._use_mtls_endpoint, + ) + ) + + if not transport_provided: + import google.auth._default # type: ignore + + if api_key_value and hasattr( + google.auth._default, "get_api_key_credentials" + ): + credentials = google.auth._default.get_api_key_credentials( + api_key_value + ) + + transport_init: Union[ + Type[GenerativeQuestionServiceTransport], + Callable[..., GenerativeQuestionServiceTransport], + ] = ( + GenerativeQuestionServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast(Callable[..., GenerativeQuestionServiceTransport], transport) + ) + # initialize with the provided callable or the passed in class + self._transport = transport_init( + credentials=credentials, + credentials_file=self._client_options.credentials_file, + host=self._api_endpoint, + scopes=self._client_options.scopes, + client_cert_source_for_mtls=self._client_cert_source, + quota_project_id=self._client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + api_audience=self._client_options.api_audience, + ) + + def update_generative_questions_feature_config( + self, + request: Optional[ + Union[ + generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest, + dict, + ] + ] = None, + *, + generative_questions_feature_config: Optional[ + generative_question.GenerativeQuestionsFeatureConfig + ] = None, + update_mask: Optional[field_mask_pb2.FieldMask] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> generative_question.GenerativeQuestionsFeatureConfig: + r"""Manages overal generative question feature state -- + enables toggling feature on and off. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import retail_v2beta + + def sample_update_generative_questions_feature_config(): + # Create a client + client = retail_v2beta.GenerativeQuestionServiceClient() + + # Initialize request argument(s) + generative_questions_feature_config = retail_v2beta.GenerativeQuestionsFeatureConfig() + generative_questions_feature_config.catalog = "catalog_value" + + request = retail_v2beta.UpdateGenerativeQuestionsFeatureConfigRequest( + generative_questions_feature_config=generative_questions_feature_config, + ) + + # Make the request + response = client.update_generative_questions_feature_config(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.retail_v2beta.types.UpdateGenerativeQuestionsFeatureConfigRequest, dict]): + The request object. Request for + UpdateGenerativeQuestionsFeatureConfig + method. + generative_questions_feature_config (google.cloud.retail_v2beta.types.GenerativeQuestionsFeatureConfig): + Required. The configuration managing + the feature state. + + This corresponds to the ``generative_questions_feature_config`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + update_mask (google.protobuf.field_mask_pb2.FieldMask): + Optional. Indicates which fields in the provided + [GenerativeQuestionsFeatureConfig][google.cloud.retail.v2beta.GenerativeQuestionsFeatureConfig] + to update. If not set or empty, all supported fields are + updated. + + This corresponds to the ``update_mask`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.retail_v2beta.types.GenerativeQuestionsFeatureConfig: + Configuration for overall generative + question feature state. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([generative_questions_feature_config, update_mask]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance( + request, + generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest, + ): + request = generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if generative_questions_feature_config is not None: + request.generative_questions_feature_config = ( + generative_questions_feature_config + ) + if update_mask is not None: + request.update_mask = update_mask + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.update_generative_questions_feature_config + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + ( + ( + "generative_questions_feature_config.catalog", + request.generative_questions_feature_config.catalog, + ), + ) + ), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + def get_generative_questions_feature_config( + self, + request: Optional[ + Union[ + generative_question_service.GetGenerativeQuestionsFeatureConfigRequest, + dict, + ] + ] = None, + *, + catalog: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> generative_question.GenerativeQuestionsFeatureConfig: + r"""Manages overal generative question feature state -- + enables toggling feature on and off. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import retail_v2beta + + def sample_get_generative_questions_feature_config(): + # Create a client + client = retail_v2beta.GenerativeQuestionServiceClient() + + # Initialize request argument(s) + request = retail_v2beta.GetGenerativeQuestionsFeatureConfigRequest( + catalog="catalog_value", + ) + + # Make the request + response = client.get_generative_questions_feature_config(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.retail_v2beta.types.GetGenerativeQuestionsFeatureConfigRequest, dict]): + The request object. Request for + GetGenerativeQuestionsFeatureConfig + method. + catalog (str): + Required. Resource name of the parent + catalog. Format: + projects/{project}/locations/{location}/catalogs/{catalog} + + This corresponds to the ``catalog`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.retail_v2beta.types.GenerativeQuestionsFeatureConfig: + Configuration for overall generative + question feature state. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([catalog]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance( + request, + generative_question_service.GetGenerativeQuestionsFeatureConfigRequest, + ): + request = ( + generative_question_service.GetGenerativeQuestionsFeatureConfigRequest( + request + ) + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if catalog is not None: + request.catalog = catalog + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.get_generative_questions_feature_config + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("catalog", request.catalog),)), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + def list_generative_question_configs( + self, + request: Optional[ + Union[ + generative_question_service.ListGenerativeQuestionConfigsRequest, dict + ] + ] = None, + *, + parent: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> generative_question_service.ListGenerativeQuestionConfigsResponse: + r"""Returns all questions for a given catalog. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import retail_v2beta + + def sample_list_generative_question_configs(): + # Create a client + client = retail_v2beta.GenerativeQuestionServiceClient() + + # Initialize request argument(s) + request = retail_v2beta.ListGenerativeQuestionConfigsRequest( + parent="parent_value", + ) + + # Make the request + response = client.list_generative_question_configs(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.retail_v2beta.types.ListGenerativeQuestionConfigsRequest, dict]): + The request object. Request for ListQuestions method. + parent (str): + Required. Resource name of the parent + catalog. Format: + projects/{project}/locations/{location}/catalogs/{catalog} + + This corresponds to the ``parent`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.retail_v2beta.types.ListGenerativeQuestionConfigsResponse: + Response for ListQuestions method. + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([parent]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance( + request, generative_question_service.ListGenerativeQuestionConfigsRequest + ): + request = generative_question_service.ListGenerativeQuestionConfigsRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if parent is not None: + request.parent = parent + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.list_generative_question_configs + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + def update_generative_question_config( + self, + request: Optional[ + Union[ + generative_question_service.UpdateGenerativeQuestionConfigRequest, dict + ] + ] = None, + *, + generative_question_config: Optional[ + generative_question.GenerativeQuestionConfig + ] = None, + update_mask: Optional[field_mask_pb2.FieldMask] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> generative_question.GenerativeQuestionConfig: + r"""Allows management of individual questions. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import retail_v2beta + + def sample_update_generative_question_config(): + # Create a client + client = retail_v2beta.GenerativeQuestionServiceClient() + + # Initialize request argument(s) + generative_question_config = retail_v2beta.GenerativeQuestionConfig() + generative_question_config.catalog = "catalog_value" + generative_question_config.facet = "facet_value" + + request = retail_v2beta.UpdateGenerativeQuestionConfigRequest( + generative_question_config=generative_question_config, + ) + + # Make the request + response = client.update_generative_question_config(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.retail_v2beta.types.UpdateGenerativeQuestionConfigRequest, dict]): + The request object. Request for + UpdateGenerativeQuestionConfig method. + generative_question_config (google.cloud.retail_v2beta.types.GenerativeQuestionConfig): + Required. The question to update. + This corresponds to the ``generative_question_config`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + update_mask (google.protobuf.field_mask_pb2.FieldMask): + Optional. Indicates which fields in the provided + [GenerativeQuestionConfig][google.cloud.retail.v2beta.GenerativeQuestionConfig] + to update. The following are NOT supported: + + - [GenerativeQuestionConfig.frequency][google.cloud.retail.v2beta.GenerativeQuestionConfig.frequency] + + If not set or empty, all supported fields are updated. + + This corresponds to the ``update_mask`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.retail_v2beta.types.GenerativeQuestionConfig: + Configuration for a single generated + question. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([generative_question_config, update_mask]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance( + request, generative_question_service.UpdateGenerativeQuestionConfigRequest + ): + request = generative_question_service.UpdateGenerativeQuestionConfigRequest( + request + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if generative_question_config is not None: + request.generative_question_config = generative_question_config + if update_mask is not None: + request.update_mask = update_mask + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.update_generative_question_config + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + ( + ( + "generative_question_config.catalog", + request.generative_question_config.catalog, + ), + ) + ), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + def batch_update_generative_question_configs( + self, + request: Optional[ + Union[ + generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest, + dict, + ] + ] = None, + *, + parent: Optional[str] = None, + requests: Optional[ + MutableSequence[ + generative_question_service.UpdateGenerativeQuestionConfigRequest + ] + ] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse: + r"""Allows management of multiple questions. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import retail_v2beta + + def sample_batch_update_generative_question_configs(): + # Create a client + client = retail_v2beta.GenerativeQuestionServiceClient() + + # Initialize request argument(s) + requests = retail_v2beta.UpdateGenerativeQuestionConfigRequest() + requests.generative_question_config.catalog = "catalog_value" + requests.generative_question_config.facet = "facet_value" + + request = retail_v2beta.BatchUpdateGenerativeQuestionConfigsRequest( + requests=requests, + ) + + # Make the request + response = client.batch_update_generative_question_configs(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.retail_v2beta.types.BatchUpdateGenerativeQuestionConfigsRequest, dict]): + The request object. Request for + BatchUpdateGenerativeQuestionConfig + method. + parent (str): + Optional. Resource name of the parent + catalog. Format: + projects/{project}/locations/{location}/catalogs/{catalog} + + This corresponds to the ``parent`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + requests (MutableSequence[google.cloud.retail_v2beta.types.UpdateGenerativeQuestionConfigRequest]): + Required. The updates question + configs. + + This corresponds to the ``requests`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.retail_v2beta.types.BatchUpdateGenerativeQuestionConfigsResponse: + Aggregated response for + UpdateGenerativeQuestionConfig method. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([parent, requests]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance( + request, + generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest, + ): + request = ( + generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest( + request + ) + ) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if parent is not None: + request.parent = parent + if requests is not None: + request.requests = requests + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.batch_update_generative_question_configs + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + def __enter__(self) -> "GenerativeQuestionServiceClient": + return self + + def __exit__(self, type, value, traceback): + """Releases underlying transport's resources. + + .. warning:: + ONLY use as a context manager if the transport is NOT shared + with other clients! Exiting the with block will CLOSE the transport + and may cause errors in other clients! + """ + self.transport.close() + + def list_operations( + self, + request: Optional[operations_pb2.ListOperationsRequest] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operations_pb2.ListOperationsResponse: + r"""Lists operations that match the specified filter in the request. + + Args: + request (:class:`~.operations_pb2.ListOperationsRequest`): + The request object. Request message for + `ListOperations` method. + retry (google.api_core.retry.Retry): Designation of what errors, + if any, should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + Returns: + ~.operations_pb2.ListOperationsResponse: + Response message for ``ListOperations`` method. + """ + # Create or coerce a protobuf request object. + # The request isn't a proto-plus wrapped type, + # so it must be constructed via keyword expansion. + if isinstance(request, dict): + request = operations_pb2.ListOperationsRequest(**request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method.wrap_method( + self._transport.list_operations, + default_timeout=None, + client_info=DEFAULT_CLIENT_INFO, + ) + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + def get_operation( + self, + request: Optional[operations_pb2.GetOperationRequest] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operations_pb2.Operation: + r"""Gets the latest state of a long-running operation. + + Args: + request (:class:`~.operations_pb2.GetOperationRequest`): + The request object. Request message for + `GetOperation` method. + retry (google.api_core.retry.Retry): Designation of what errors, + if any, should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + Returns: + ~.operations_pb2.Operation: + An ``Operation`` object. + """ + # Create or coerce a protobuf request object. + # The request isn't a proto-plus wrapped type, + # so it must be constructed via keyword expansion. + if isinstance(request, dict): + request = operations_pb2.GetOperationRequest(**request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method.wrap_method( + self._transport.get_operation, + default_timeout=None, + client_info=DEFAULT_CLIENT_INFO, + ) + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=package_version.__version__ +) + + +__all__ = ("GenerativeQuestionServiceClient",) diff --git a/packages/google-cloud-retail/google/cloud/retail_v2beta/services/generative_question_service/transports/__init__.py b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/generative_question_service/transports/__init__.py new file mode 100644 index 000000000000..9e57f7d430ba --- /dev/null +++ b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/generative_question_service/transports/__init__.py @@ -0,0 +1,41 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +from typing import Dict, Type + +from .base import GenerativeQuestionServiceTransport +from .grpc import GenerativeQuestionServiceGrpcTransport +from .grpc_asyncio import GenerativeQuestionServiceGrpcAsyncIOTransport +from .rest import ( + GenerativeQuestionServiceRestInterceptor, + GenerativeQuestionServiceRestTransport, +) + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[GenerativeQuestionServiceTransport]] +_transport_registry["grpc"] = GenerativeQuestionServiceGrpcTransport +_transport_registry["grpc_asyncio"] = GenerativeQuestionServiceGrpcAsyncIOTransport +_transport_registry["rest"] = GenerativeQuestionServiceRestTransport + +__all__ = ( + "GenerativeQuestionServiceTransport", + "GenerativeQuestionServiceGrpcTransport", + "GenerativeQuestionServiceGrpcAsyncIOTransport", + "GenerativeQuestionServiceRestTransport", + "GenerativeQuestionServiceRestInterceptor", +) diff --git a/packages/google-cloud-retail/google/cloud/retail_v2beta/services/generative_question_service/transports/base.py b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/generative_question_service/transports/base.py new file mode 100644 index 000000000000..9a967141097c --- /dev/null +++ b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/generative_question_service/transports/base.py @@ -0,0 +1,262 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import abc +from typing import Awaitable, Callable, Dict, Optional, Sequence, Union + +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.cloud.location import locations_pb2 # type: ignore +from google.longrunning import operations_pb2 # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.cloud.retail_v2beta import gapic_version as package_version +from google.cloud.retail_v2beta.types import ( + generative_question, + generative_question_service, +) + +DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=package_version.__version__ +) + + +class GenerativeQuestionServiceTransport(abc.ABC): + """Abstract transport class for GenerativeQuestionService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/cloud-platform",) + + DEFAULT_HOST: str = "retail.googleapis.com" + + def __init__( + self, + *, + host: str = DEFAULT_HOST, + credentials: Optional[ga_credentials.Credentials] = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + quota_project_id: Optional[str] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, + api_audience: Optional[str] = None, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to (default: 'retail.googleapis.com'). + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, **scopes_kwargs, quota_project_id=quota_project_id + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr(service_account.Credentials, "with_always_use_jwt_access") + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.update_generative_questions_feature_config: gapic_v1.method.wrap_method( + self.update_generative_questions_feature_config, + default_timeout=None, + client_info=client_info, + ), + self.get_generative_questions_feature_config: gapic_v1.method.wrap_method( + self.get_generative_questions_feature_config, + default_timeout=None, + client_info=client_info, + ), + self.list_generative_question_configs: gapic_v1.method.wrap_method( + self.list_generative_question_configs, + default_timeout=None, + client_info=client_info, + ), + self.update_generative_question_config: gapic_v1.method.wrap_method( + self.update_generative_question_config, + default_timeout=None, + client_info=client_info, + ), + self.batch_update_generative_question_configs: gapic_v1.method.wrap_method( + self.batch_update_generative_question_configs, + default_timeout=None, + client_info=client_info, + ), + } + + def close(self): + """Closes resources associated with the transport. + + .. warning:: + Only call this method if the transport is NOT shared + with other clients - this may cause errors in other clients! + """ + raise NotImplementedError() + + @property + def update_generative_questions_feature_config( + self, + ) -> Callable[ + [generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest], + Union[ + generative_question.GenerativeQuestionsFeatureConfig, + Awaitable[generative_question.GenerativeQuestionsFeatureConfig], + ], + ]: + raise NotImplementedError() + + @property + def get_generative_questions_feature_config( + self, + ) -> Callable[ + [generative_question_service.GetGenerativeQuestionsFeatureConfigRequest], + Union[ + generative_question.GenerativeQuestionsFeatureConfig, + Awaitable[generative_question.GenerativeQuestionsFeatureConfig], + ], + ]: + raise NotImplementedError() + + @property + def list_generative_question_configs( + self, + ) -> Callable[ + [generative_question_service.ListGenerativeQuestionConfigsRequest], + Union[ + generative_question_service.ListGenerativeQuestionConfigsResponse, + Awaitable[ + generative_question_service.ListGenerativeQuestionConfigsResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def update_generative_question_config( + self, + ) -> Callable[ + [generative_question_service.UpdateGenerativeQuestionConfigRequest], + Union[ + generative_question.GenerativeQuestionConfig, + Awaitable[generative_question.GenerativeQuestionConfig], + ], + ]: + raise NotImplementedError() + + @property + def batch_update_generative_question_configs( + self, + ) -> Callable[ + [generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest], + Union[ + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse, + Awaitable[ + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse + ], + ], + ]: + raise NotImplementedError() + + @property + def list_operations( + self, + ) -> Callable[ + [operations_pb2.ListOperationsRequest], + Union[ + operations_pb2.ListOperationsResponse, + Awaitable[operations_pb2.ListOperationsResponse], + ], + ]: + raise NotImplementedError() + + @property + def get_operation( + self, + ) -> Callable[ + [operations_pb2.GetOperationRequest], + Union[operations_pb2.Operation, Awaitable[operations_pb2.Operation]], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("GenerativeQuestionServiceTransport",) diff --git a/packages/google-cloud-retail/google/cloud/retail_v2beta/services/generative_question_service/transports/grpc.py b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/generative_question_service/transports/grpc.py new file mode 100644 index 000000000000..44cca87df83d --- /dev/null +++ b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/generative_question_service/transports/grpc.py @@ -0,0 +1,449 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from typing import Callable, Dict, Optional, Sequence, Tuple, Union +import warnings + +from google.api_core import gapic_v1, grpc_helpers +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.cloud.location import locations_pb2 # type: ignore +from google.longrunning import operations_pb2 # type: ignore +import grpc # type: ignore + +from google.cloud.retail_v2beta.types import ( + generative_question, + generative_question_service, +) + +from .base import DEFAULT_CLIENT_INFO, GenerativeQuestionServiceTransport + + +class GenerativeQuestionServiceGrpcTransport(GenerativeQuestionServiceTransport): + """gRPC backend transport for GenerativeQuestionService. + + Service for managing LLM generated questions in search + serving. + + This class defines the same methods as the primary client, so the + primary client can load the underlying transport implementation + and call it. + + It sends protocol buffers over the wire using gRPC (which is built on + top of HTTP/2); the ``grpcio`` package must be installed. + """ + + _stubs: Dict[str, Callable] + + def __init__( + self, + *, + host: str = "retail.googleapis.com", + credentials: Optional[ga_credentials.Credentials] = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + channel: Optional[Union[grpc.Channel, Callable[..., grpc.Channel]]] = None, + api_mtls_endpoint: Optional[str] = None, + client_cert_source: Optional[Callable[[], Tuple[bytes, bytes]]] = None, + ssl_channel_credentials: Optional[grpc.ChannelCredentials] = None, + client_cert_source_for_mtls: Optional[Callable[[], Tuple[bytes, bytes]]] = None, + quota_project_id: Optional[str] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, + api_audience: Optional[str] = None, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to (default: 'retail.googleapis.com'). + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if a ``channel`` instance is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if a ``channel`` instance is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if a ``channel`` instance is provided. + channel (Optional[Union[grpc.Channel, Callable[..., grpc.Channel]]]): + A ``Channel`` instance through which to make calls, or a Callable + that constructs and returns one. If set to None, ``self.create_channel`` + is used to create the channel. If a Callable is given, it will be called + with the same arguments as used in ``self.create_channel``. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if a ``channel`` instance is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if a ``channel`` instance or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn("client_cert_source is deprecated", DeprecationWarning) + + if isinstance(channel, grpc.Channel): + # Ignore credentials if a channel was passed. + credentials = None + self._ignore_credentials = True + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + else: + self._ssl_channel_credentials = SslCredentials().ssl_credentials + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + api_audience=api_audience, + ) + + if not self._grpc_channel: + # initialize with the provided callable or the default channel + channel_init = channel or type(self).create_channel + self._grpc_channel = channel_init( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "retail.googleapis.com", + credentials: Optional[ga_credentials.Credentials] = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + quota_project_id: Optional[str] = None, + **kwargs, + ) -> grpc.Channel: + """Create and return a gRPC channel object. + Args: + host (Optional[str]): The host for the channel to use. + credentials (Optional[~.Credentials]): The + authorization credentials to attach to requests. These + credentials identify this application to the service. If + none are specified, the client will attempt to ascertain + the credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def update_generative_questions_feature_config( + self, + ) -> Callable[ + [generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest], + generative_question.GenerativeQuestionsFeatureConfig, + ]: + r"""Return a callable for the update generative questions + feature config method over gRPC. + + Manages overal generative question feature state -- + enables toggling feature on and off. + + Returns: + Callable[[~.UpdateGenerativeQuestionsFeatureConfigRequest], + ~.GenerativeQuestionsFeatureConfig]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "update_generative_questions_feature_config" not in self._stubs: + self._stubs[ + "update_generative_questions_feature_config" + ] = self.grpc_channel.unary_unary( + "/google.cloud.retail.v2beta.GenerativeQuestionService/UpdateGenerativeQuestionsFeatureConfig", + request_serializer=generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest.serialize, + response_deserializer=generative_question.GenerativeQuestionsFeatureConfig.deserialize, + ) + return self._stubs["update_generative_questions_feature_config"] + + @property + def get_generative_questions_feature_config( + self, + ) -> Callable[ + [generative_question_service.GetGenerativeQuestionsFeatureConfigRequest], + generative_question.GenerativeQuestionsFeatureConfig, + ]: + r"""Return a callable for the get generative questions + feature config method over gRPC. + + Manages overal generative question feature state -- + enables toggling feature on and off. + + Returns: + Callable[[~.GetGenerativeQuestionsFeatureConfigRequest], + ~.GenerativeQuestionsFeatureConfig]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "get_generative_questions_feature_config" not in self._stubs: + self._stubs[ + "get_generative_questions_feature_config" + ] = self.grpc_channel.unary_unary( + "/google.cloud.retail.v2beta.GenerativeQuestionService/GetGenerativeQuestionsFeatureConfig", + request_serializer=generative_question_service.GetGenerativeQuestionsFeatureConfigRequest.serialize, + response_deserializer=generative_question.GenerativeQuestionsFeatureConfig.deserialize, + ) + return self._stubs["get_generative_questions_feature_config"] + + @property + def list_generative_question_configs( + self, + ) -> Callable[ + [generative_question_service.ListGenerativeQuestionConfigsRequest], + generative_question_service.ListGenerativeQuestionConfigsResponse, + ]: + r"""Return a callable for the list generative question + configs method over gRPC. + + Returns all questions for a given catalog. + + Returns: + Callable[[~.ListGenerativeQuestionConfigsRequest], + ~.ListGenerativeQuestionConfigsResponse]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "list_generative_question_configs" not in self._stubs: + self._stubs[ + "list_generative_question_configs" + ] = self.grpc_channel.unary_unary( + "/google.cloud.retail.v2beta.GenerativeQuestionService/ListGenerativeQuestionConfigs", + request_serializer=generative_question_service.ListGenerativeQuestionConfigsRequest.serialize, + response_deserializer=generative_question_service.ListGenerativeQuestionConfigsResponse.deserialize, + ) + return self._stubs["list_generative_question_configs"] + + @property + def update_generative_question_config( + self, + ) -> Callable[ + [generative_question_service.UpdateGenerativeQuestionConfigRequest], + generative_question.GenerativeQuestionConfig, + ]: + r"""Return a callable for the update generative question + config method over gRPC. + + Allows management of individual questions. + + Returns: + Callable[[~.UpdateGenerativeQuestionConfigRequest], + ~.GenerativeQuestionConfig]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "update_generative_question_config" not in self._stubs: + self._stubs[ + "update_generative_question_config" + ] = self.grpc_channel.unary_unary( + "/google.cloud.retail.v2beta.GenerativeQuestionService/UpdateGenerativeQuestionConfig", + request_serializer=generative_question_service.UpdateGenerativeQuestionConfigRequest.serialize, + response_deserializer=generative_question.GenerativeQuestionConfig.deserialize, + ) + return self._stubs["update_generative_question_config"] + + @property + def batch_update_generative_question_configs( + self, + ) -> Callable[ + [generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest], + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse, + ]: + r"""Return a callable for the batch update generative + question configs method over gRPC. + + Allows management of multiple questions. + + Returns: + Callable[[~.BatchUpdateGenerativeQuestionConfigsRequest], + ~.BatchUpdateGenerativeQuestionConfigsResponse]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "batch_update_generative_question_configs" not in self._stubs: + self._stubs[ + "batch_update_generative_question_configs" + ] = self.grpc_channel.unary_unary( + "/google.cloud.retail.v2beta.GenerativeQuestionService/BatchUpdateGenerativeQuestionConfigs", + request_serializer=generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest.serialize, + response_deserializer=generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse.deserialize, + ) + return self._stubs["batch_update_generative_question_configs"] + + def close(self): + self.grpc_channel.close() + + @property + def get_operation( + self, + ) -> Callable[[operations_pb2.GetOperationRequest], operations_pb2.Operation]: + r"""Return a callable for the get_operation method over gRPC.""" + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "get_operation" not in self._stubs: + self._stubs["get_operation"] = self.grpc_channel.unary_unary( + "/google.longrunning.Operations/GetOperation", + request_serializer=operations_pb2.GetOperationRequest.SerializeToString, + response_deserializer=operations_pb2.Operation.FromString, + ) + return self._stubs["get_operation"] + + @property + def list_operations( + self, + ) -> Callable[ + [operations_pb2.ListOperationsRequest], operations_pb2.ListOperationsResponse + ]: + r"""Return a callable for the list_operations method over gRPC.""" + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "list_operations" not in self._stubs: + self._stubs["list_operations"] = self.grpc_channel.unary_unary( + "/google.longrunning.Operations/ListOperations", + request_serializer=operations_pb2.ListOperationsRequest.SerializeToString, + response_deserializer=operations_pb2.ListOperationsResponse.FromString, + ) + return self._stubs["list_operations"] + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("GenerativeQuestionServiceGrpcTransport",) diff --git a/packages/google-cloud-retail/google/cloud/retail_v2beta/services/generative_question_service/transports/grpc_asyncio.py b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/generative_question_service/transports/grpc_asyncio.py new file mode 100644 index 000000000000..df68cc1d710e --- /dev/null +++ b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/generative_question_service/transports/grpc_asyncio.py @@ -0,0 +1,481 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union +import warnings + +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1, grpc_helpers_async +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.cloud.location import locations_pb2 # type: ignore +from google.longrunning import operations_pb2 # type: ignore +import grpc # type: ignore +from grpc.experimental import aio # type: ignore + +from google.cloud.retail_v2beta.types import ( + generative_question, + generative_question_service, +) + +from .base import DEFAULT_CLIENT_INFO, GenerativeQuestionServiceTransport +from .grpc import GenerativeQuestionServiceGrpcTransport + + +class GenerativeQuestionServiceGrpcAsyncIOTransport(GenerativeQuestionServiceTransport): + """gRPC AsyncIO backend transport for GenerativeQuestionService. + + Service for managing LLM generated questions in search + serving. + + This class defines the same methods as the primary client, so the + primary client can load the underlying transport implementation + and call it. + + It sends protocol buffers over the wire using gRPC (which is built on + top of HTTP/2); the ``grpcio`` package must be installed. + """ + + _grpc_channel: aio.Channel + _stubs: Dict[str, Callable] = {} + + @classmethod + def create_channel( + cls, + host: str = "retail.googleapis.com", + credentials: Optional[ga_credentials.Credentials] = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + quota_project_id: Optional[str] = None, + **kwargs, + ) -> aio.Channel: + """Create and return a gRPC AsyncIO channel object. + Args: + host (Optional[str]): The host for the channel to use. + credentials (Optional[~.Credentials]): The + authorization credentials to attach to requests. These + credentials identify this application to the service. If + none are specified, the client will attempt to ascertain + the credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + aio.Channel: A gRPC AsyncIO channel object. + """ + + return grpc_helpers_async.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + def __init__( + self, + *, + host: str = "retail.googleapis.com", + credentials: Optional[ga_credentials.Credentials] = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + channel: Optional[Union[aio.Channel, Callable[..., aio.Channel]]] = None, + api_mtls_endpoint: Optional[str] = None, + client_cert_source: Optional[Callable[[], Tuple[bytes, bytes]]] = None, + ssl_channel_credentials: Optional[grpc.ChannelCredentials] = None, + client_cert_source_for_mtls: Optional[Callable[[], Tuple[bytes, bytes]]] = None, + quota_project_id: Optional[str] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, + api_audience: Optional[str] = None, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to (default: 'retail.googleapis.com'). + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if a ``channel`` instance is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if a ``channel`` instance is provided. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + channel (Optional[Union[aio.Channel, Callable[..., aio.Channel]]]): + A ``Channel`` instance through which to make calls, or a Callable + that constructs and returns one. If set to None, ``self.create_channel`` + is used to create the channel. If a Callable is given, it will be called + with the same arguments as used in ``self.create_channel``. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if a ``channel`` instance is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if a ``channel`` instance or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn("client_cert_source is deprecated", DeprecationWarning) + + if isinstance(channel, aio.Channel): + # Ignore credentials if a channel was passed. + credentials = None + self._ignore_credentials = True + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + else: + self._ssl_channel_credentials = SslCredentials().ssl_credentials + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + api_audience=api_audience, + ) + + if not self._grpc_channel: + # initialize with the provided callable or the default channel + channel_init = channel or type(self).create_channel + self._grpc_channel = channel_init( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @property + def grpc_channel(self) -> aio.Channel: + """Create the channel designed to connect to this service. + + This property caches on the instance; repeated calls return + the same channel. + """ + # Return the channel from cache. + return self._grpc_channel + + @property + def update_generative_questions_feature_config( + self, + ) -> Callable[ + [generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest], + Awaitable[generative_question.GenerativeQuestionsFeatureConfig], + ]: + r"""Return a callable for the update generative questions + feature config method over gRPC. + + Manages overal generative question feature state -- + enables toggling feature on and off. + + Returns: + Callable[[~.UpdateGenerativeQuestionsFeatureConfigRequest], + Awaitable[~.GenerativeQuestionsFeatureConfig]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "update_generative_questions_feature_config" not in self._stubs: + self._stubs[ + "update_generative_questions_feature_config" + ] = self.grpc_channel.unary_unary( + "/google.cloud.retail.v2beta.GenerativeQuestionService/UpdateGenerativeQuestionsFeatureConfig", + request_serializer=generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest.serialize, + response_deserializer=generative_question.GenerativeQuestionsFeatureConfig.deserialize, + ) + return self._stubs["update_generative_questions_feature_config"] + + @property + def get_generative_questions_feature_config( + self, + ) -> Callable[ + [generative_question_service.GetGenerativeQuestionsFeatureConfigRequest], + Awaitable[generative_question.GenerativeQuestionsFeatureConfig], + ]: + r"""Return a callable for the get generative questions + feature config method over gRPC. + + Manages overal generative question feature state -- + enables toggling feature on and off. + + Returns: + Callable[[~.GetGenerativeQuestionsFeatureConfigRequest], + Awaitable[~.GenerativeQuestionsFeatureConfig]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "get_generative_questions_feature_config" not in self._stubs: + self._stubs[ + "get_generative_questions_feature_config" + ] = self.grpc_channel.unary_unary( + "/google.cloud.retail.v2beta.GenerativeQuestionService/GetGenerativeQuestionsFeatureConfig", + request_serializer=generative_question_service.GetGenerativeQuestionsFeatureConfigRequest.serialize, + response_deserializer=generative_question.GenerativeQuestionsFeatureConfig.deserialize, + ) + return self._stubs["get_generative_questions_feature_config"] + + @property + def list_generative_question_configs( + self, + ) -> Callable[ + [generative_question_service.ListGenerativeQuestionConfigsRequest], + Awaitable[generative_question_service.ListGenerativeQuestionConfigsResponse], + ]: + r"""Return a callable for the list generative question + configs method over gRPC. + + Returns all questions for a given catalog. + + Returns: + Callable[[~.ListGenerativeQuestionConfigsRequest], + Awaitable[~.ListGenerativeQuestionConfigsResponse]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "list_generative_question_configs" not in self._stubs: + self._stubs[ + "list_generative_question_configs" + ] = self.grpc_channel.unary_unary( + "/google.cloud.retail.v2beta.GenerativeQuestionService/ListGenerativeQuestionConfigs", + request_serializer=generative_question_service.ListGenerativeQuestionConfigsRequest.serialize, + response_deserializer=generative_question_service.ListGenerativeQuestionConfigsResponse.deserialize, + ) + return self._stubs["list_generative_question_configs"] + + @property + def update_generative_question_config( + self, + ) -> Callable[ + [generative_question_service.UpdateGenerativeQuestionConfigRequest], + Awaitable[generative_question.GenerativeQuestionConfig], + ]: + r"""Return a callable for the update generative question + config method over gRPC. + + Allows management of individual questions. + + Returns: + Callable[[~.UpdateGenerativeQuestionConfigRequest], + Awaitable[~.GenerativeQuestionConfig]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "update_generative_question_config" not in self._stubs: + self._stubs[ + "update_generative_question_config" + ] = self.grpc_channel.unary_unary( + "/google.cloud.retail.v2beta.GenerativeQuestionService/UpdateGenerativeQuestionConfig", + request_serializer=generative_question_service.UpdateGenerativeQuestionConfigRequest.serialize, + response_deserializer=generative_question.GenerativeQuestionConfig.deserialize, + ) + return self._stubs["update_generative_question_config"] + + @property + def batch_update_generative_question_configs( + self, + ) -> Callable[ + [generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest], + Awaitable[ + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse + ], + ]: + r"""Return a callable for the batch update generative + question configs method over gRPC. + + Allows management of multiple questions. + + Returns: + Callable[[~.BatchUpdateGenerativeQuestionConfigsRequest], + Awaitable[~.BatchUpdateGenerativeQuestionConfigsResponse]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "batch_update_generative_question_configs" not in self._stubs: + self._stubs[ + "batch_update_generative_question_configs" + ] = self.grpc_channel.unary_unary( + "/google.cloud.retail.v2beta.GenerativeQuestionService/BatchUpdateGenerativeQuestionConfigs", + request_serializer=generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest.serialize, + response_deserializer=generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse.deserialize, + ) + return self._stubs["batch_update_generative_question_configs"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.update_generative_questions_feature_config: gapic_v1.method_async.wrap_method( + self.update_generative_questions_feature_config, + default_timeout=None, + client_info=client_info, + ), + self.get_generative_questions_feature_config: gapic_v1.method_async.wrap_method( + self.get_generative_questions_feature_config, + default_timeout=None, + client_info=client_info, + ), + self.list_generative_question_configs: gapic_v1.method_async.wrap_method( + self.list_generative_question_configs, + default_timeout=None, + client_info=client_info, + ), + self.update_generative_question_config: gapic_v1.method_async.wrap_method( + self.update_generative_question_config, + default_timeout=None, + client_info=client_info, + ), + self.batch_update_generative_question_configs: gapic_v1.method_async.wrap_method( + self.batch_update_generative_question_configs, + default_timeout=None, + client_info=client_info, + ), + } + + def close(self): + return self.grpc_channel.close() + + @property + def get_operation( + self, + ) -> Callable[[operations_pb2.GetOperationRequest], operations_pb2.Operation]: + r"""Return a callable for the get_operation method over gRPC.""" + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "get_operation" not in self._stubs: + self._stubs["get_operation"] = self.grpc_channel.unary_unary( + "/google.longrunning.Operations/GetOperation", + request_serializer=operations_pb2.GetOperationRequest.SerializeToString, + response_deserializer=operations_pb2.Operation.FromString, + ) + return self._stubs["get_operation"] + + @property + def list_operations( + self, + ) -> Callable[ + [operations_pb2.ListOperationsRequest], operations_pb2.ListOperationsResponse + ]: + r"""Return a callable for the list_operations method over gRPC.""" + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "list_operations" not in self._stubs: + self._stubs["list_operations"] = self.grpc_channel.unary_unary( + "/google.longrunning.Operations/ListOperations", + request_serializer=operations_pb2.ListOperationsRequest.SerializeToString, + response_deserializer=operations_pb2.ListOperationsResponse.FromString, + ) + return self._stubs["list_operations"] + + +__all__ = ("GenerativeQuestionServiceGrpcAsyncIOTransport",) diff --git a/packages/google-cloud-retail/google/cloud/retail_v2beta/services/generative_question_service/transports/rest.py b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/generative_question_service/transports/rest.py new file mode 100644 index 000000000000..4c9d37fb0766 --- /dev/null +++ b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/generative_question_service/transports/rest.py @@ -0,0 +1,1118 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +import dataclasses +import json # type: ignore +import re +from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple, Union +import warnings + +from google.api_core import gapic_v1, path_template, rest_helpers, rest_streaming +from google.api_core import exceptions as core_exceptions +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.transport.requests import AuthorizedSession # type: ignore +from google.cloud.location import locations_pb2 # type: ignore +from google.protobuf import json_format +import grpc # type: ignore +from requests import __version__ as requests_version + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault, None] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object, None] # type: ignore + + +from google.longrunning import operations_pb2 # type: ignore + +from google.cloud.retail_v2beta.types import ( + generative_question, + generative_question_service, +) + +from .base import DEFAULT_CLIENT_INFO as BASE_DEFAULT_CLIENT_INFO +from .base import GenerativeQuestionServiceTransport + +DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=BASE_DEFAULT_CLIENT_INFO.gapic_version, + grpc_version=None, + rest_version=requests_version, +) + + +class GenerativeQuestionServiceRestInterceptor: + """Interceptor for GenerativeQuestionService. + + Interceptors are used to manipulate requests, request metadata, and responses + in arbitrary ways. + Example use cases include: + * Logging + * Verifying requests according to service or custom semantics + * Stripping extraneous information from responses + + These use cases and more can be enabled by injecting an + instance of a custom subclass when constructing the GenerativeQuestionServiceRestTransport. + + .. code-block:: python + class MyCustomGenerativeQuestionServiceInterceptor(GenerativeQuestionServiceRestInterceptor): + def pre_batch_update_generative_question_configs(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_batch_update_generative_question_configs(self, response): + logging.log(f"Received response: {response}") + return response + + def pre_get_generative_questions_feature_config(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_get_generative_questions_feature_config(self, response): + logging.log(f"Received response: {response}") + return response + + def pre_list_generative_question_configs(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_list_generative_question_configs(self, response): + logging.log(f"Received response: {response}") + return response + + def pre_update_generative_question_config(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_update_generative_question_config(self, response): + logging.log(f"Received response: {response}") + return response + + def pre_update_generative_questions_feature_config(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_update_generative_questions_feature_config(self, response): + logging.log(f"Received response: {response}") + return response + + transport = GenerativeQuestionServiceRestTransport(interceptor=MyCustomGenerativeQuestionServiceInterceptor()) + client = GenerativeQuestionServiceClient(transport=transport) + + + """ + + def pre_batch_update_generative_question_configs( + self, + request: generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[ + generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest, + Sequence[Tuple[str, str]], + ]: + """Pre-rpc interceptor for batch_update_generative_question_configs + + Override in a subclass to manipulate the request or metadata + before they are sent to the GenerativeQuestionService server. + """ + return request, metadata + + def post_batch_update_generative_question_configs( + self, + response: generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse, + ) -> generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse: + """Post-rpc interceptor for batch_update_generative_question_configs + + Override in a subclass to manipulate the response + after it is returned by the GenerativeQuestionService server but before + it is returned to user code. + """ + return response + + def pre_get_generative_questions_feature_config( + self, + request: generative_question_service.GetGenerativeQuestionsFeatureConfigRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[ + generative_question_service.GetGenerativeQuestionsFeatureConfigRequest, + Sequence[Tuple[str, str]], + ]: + """Pre-rpc interceptor for get_generative_questions_feature_config + + Override in a subclass to manipulate the request or metadata + before they are sent to the GenerativeQuestionService server. + """ + return request, metadata + + def post_get_generative_questions_feature_config( + self, response: generative_question.GenerativeQuestionsFeatureConfig + ) -> generative_question.GenerativeQuestionsFeatureConfig: + """Post-rpc interceptor for get_generative_questions_feature_config + + Override in a subclass to manipulate the response + after it is returned by the GenerativeQuestionService server but before + it is returned to user code. + """ + return response + + def pre_list_generative_question_configs( + self, + request: generative_question_service.ListGenerativeQuestionConfigsRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[ + generative_question_service.ListGenerativeQuestionConfigsRequest, + Sequence[Tuple[str, str]], + ]: + """Pre-rpc interceptor for list_generative_question_configs + + Override in a subclass to manipulate the request or metadata + before they are sent to the GenerativeQuestionService server. + """ + return request, metadata + + def post_list_generative_question_configs( + self, + response: generative_question_service.ListGenerativeQuestionConfigsResponse, + ) -> generative_question_service.ListGenerativeQuestionConfigsResponse: + """Post-rpc interceptor for list_generative_question_configs + + Override in a subclass to manipulate the response + after it is returned by the GenerativeQuestionService server but before + it is returned to user code. + """ + return response + + def pre_update_generative_question_config( + self, + request: generative_question_service.UpdateGenerativeQuestionConfigRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[ + generative_question_service.UpdateGenerativeQuestionConfigRequest, + Sequence[Tuple[str, str]], + ]: + """Pre-rpc interceptor for update_generative_question_config + + Override in a subclass to manipulate the request or metadata + before they are sent to the GenerativeQuestionService server. + """ + return request, metadata + + def post_update_generative_question_config( + self, response: generative_question.GenerativeQuestionConfig + ) -> generative_question.GenerativeQuestionConfig: + """Post-rpc interceptor for update_generative_question_config + + Override in a subclass to manipulate the response + after it is returned by the GenerativeQuestionService server but before + it is returned to user code. + """ + return response + + def pre_update_generative_questions_feature_config( + self, + request: generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[ + generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest, + Sequence[Tuple[str, str]], + ]: + """Pre-rpc interceptor for update_generative_questions_feature_config + + Override in a subclass to manipulate the request or metadata + before they are sent to the GenerativeQuestionService server. + """ + return request, metadata + + def post_update_generative_questions_feature_config( + self, response: generative_question.GenerativeQuestionsFeatureConfig + ) -> generative_question.GenerativeQuestionsFeatureConfig: + """Post-rpc interceptor for update_generative_questions_feature_config + + Override in a subclass to manipulate the response + after it is returned by the GenerativeQuestionService server but before + it is returned to user code. + """ + return response + + def pre_get_operation( + self, + request: operations_pb2.GetOperationRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[operations_pb2.GetOperationRequest, Sequence[Tuple[str, str]]]: + """Pre-rpc interceptor for get_operation + + Override in a subclass to manipulate the request or metadata + before they are sent to the GenerativeQuestionService server. + """ + return request, metadata + + def post_get_operation( + self, response: operations_pb2.Operation + ) -> operations_pb2.Operation: + """Post-rpc interceptor for get_operation + + Override in a subclass to manipulate the response + after it is returned by the GenerativeQuestionService server but before + it is returned to user code. + """ + return response + + def pre_list_operations( + self, + request: operations_pb2.ListOperationsRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[operations_pb2.ListOperationsRequest, Sequence[Tuple[str, str]]]: + """Pre-rpc interceptor for list_operations + + Override in a subclass to manipulate the request or metadata + before they are sent to the GenerativeQuestionService server. + """ + return request, metadata + + def post_list_operations( + self, response: operations_pb2.ListOperationsResponse + ) -> operations_pb2.ListOperationsResponse: + """Post-rpc interceptor for list_operations + + Override in a subclass to manipulate the response + after it is returned by the GenerativeQuestionService server but before + it is returned to user code. + """ + return response + + +@dataclasses.dataclass +class GenerativeQuestionServiceRestStub: + _session: AuthorizedSession + _host: str + _interceptor: GenerativeQuestionServiceRestInterceptor + + +class GenerativeQuestionServiceRestTransport(GenerativeQuestionServiceTransport): + """REST backend transport for GenerativeQuestionService. + + Service for managing LLM generated questions in search + serving. + + This class defines the same methods as the primary client, so the + primary client can load the underlying transport implementation + and call it. + + It sends JSON representations of protocol buffers over HTTP/1.1 + + """ + + def __init__( + self, + *, + host: str = "retail.googleapis.com", + credentials: Optional[ga_credentials.Credentials] = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + client_cert_source_for_mtls: Optional[Callable[[], Tuple[bytes, bytes]]] = None, + quota_project_id: Optional[str] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, + url_scheme: str = "https", + interceptor: Optional[GenerativeQuestionServiceRestInterceptor] = None, + api_audience: Optional[str] = None, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to (default: 'retail.googleapis.com'). + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + client_cert_source_for_mtls (Callable[[], Tuple[bytes, bytes]]): Client + certificate to configure mutual TLS HTTP channel. It is ignored + if ``channel`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you are developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + url_scheme: the protocol scheme for the API endpoint. Normally + "https", but for testing or local servers, + "http" can be specified. + """ + # Run the base constructor + # TODO(yon-mg): resolve other ctor params i.e. scopes, quota, etc. + # TODO: When custom host (api_endpoint) is set, `scopes` must *also* be set on the + # credentials object + maybe_url_match = re.match("^(?Phttp(?:s)?://)?(?P.*)$", host) + if maybe_url_match is None: + raise ValueError( + f"Unexpected hostname structure: {host}" + ) # pragma: NO COVER + + url_match_items = maybe_url_match.groupdict() + + host = f"{url_scheme}://{host}" if not url_match_items["scheme"] else host + + super().__init__( + host=host, + credentials=credentials, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + api_audience=api_audience, + ) + self._session = AuthorizedSession( + self._credentials, default_host=self.DEFAULT_HOST + ) + if client_cert_source_for_mtls: + self._session.configure_mtls_channel(client_cert_source_for_mtls) + self._interceptor = interceptor or GenerativeQuestionServiceRestInterceptor() + self._prep_wrapped_messages(client_info) + + class _BatchUpdateGenerativeQuestionConfigs(GenerativeQuestionServiceRestStub): + def __hash__(self): + return hash("BatchUpdateGenerativeQuestionConfigs") + + __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} + + @classmethod + def _get_unset_required_fields(cls, message_dict): + return { + k: v + for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items() + if k not in message_dict + } + + def __call__( + self, + request: generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse: + r"""Call the batch update generative + question configs method over HTTP. + + Args: + request (~.generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest): + The request object. Request for + BatchUpdateGenerativeQuestionConfig + method. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + ~.generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse: + Aggregated response for + UpdateGenerativeQuestionConfig method. + + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "post", + "uri": "/v2beta/{parent=projects/*/locations/*/catalogs/*}/generativeQuestion:batchUpdate", + "body": "*", + }, + ] + ( + request, + metadata, + ) = self._interceptor.pre_batch_update_generative_question_configs( + request, metadata + ) + pb_request = generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest.pb( + request + ) + transcoded_request = path_template.transcode(http_options, pb_request) + + # Jsonify the request body + + body = json_format.MessageToJson( + transcoded_request["body"], use_integers_for_enums=True + ) + uri = transcoded_request["uri"] + method = transcoded_request["method"] + + # Jsonify the query params + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + use_integers_for_enums=True, + ) + ) + query_params.update(self._get_unset_required_fields(query_params)) + + query_params["$alt"] = "json;enum-encoding=int" + + # Send the request + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(self._session, method)( + "{host}{uri}".format(host=self._host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + data=body, + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + # Return the response + resp = ( + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse() + ) + pb_resp = generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse.pb( + resp + ) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + resp = self._interceptor.post_batch_update_generative_question_configs(resp) + return resp + + class _GetGenerativeQuestionsFeatureConfig(GenerativeQuestionServiceRestStub): + def __hash__(self): + return hash("GetGenerativeQuestionsFeatureConfig") + + __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} + + @classmethod + def _get_unset_required_fields(cls, message_dict): + return { + k: v + for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items() + if k not in message_dict + } + + def __call__( + self, + request: generative_question_service.GetGenerativeQuestionsFeatureConfigRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> generative_question.GenerativeQuestionsFeatureConfig: + r"""Call the get generative questions + feature config method over HTTP. + + Args: + request (~.generative_question_service.GetGenerativeQuestionsFeatureConfigRequest): + The request object. Request for + GetGenerativeQuestionsFeatureConfig + method. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + ~.generative_question.GenerativeQuestionsFeatureConfig: + Configuration for overall generative + question feature state. + + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "get", + "uri": "/v2beta/{catalog=projects/*/locations/*/catalogs/*}/generativeQuestionFeature", + }, + ] + ( + request, + metadata, + ) = self._interceptor.pre_get_generative_questions_feature_config( + request, metadata + ) + pb_request = generative_question_service.GetGenerativeQuestionsFeatureConfigRequest.pb( + request + ) + transcoded_request = path_template.transcode(http_options, pb_request) + + uri = transcoded_request["uri"] + method = transcoded_request["method"] + + # Jsonify the query params + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + use_integers_for_enums=True, + ) + ) + query_params.update(self._get_unset_required_fields(query_params)) + + query_params["$alt"] = "json;enum-encoding=int" + + # Send the request + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(self._session, method)( + "{host}{uri}".format(host=self._host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + # Return the response + resp = generative_question.GenerativeQuestionsFeatureConfig() + pb_resp = generative_question.GenerativeQuestionsFeatureConfig.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + resp = self._interceptor.post_get_generative_questions_feature_config(resp) + return resp + + class _ListGenerativeQuestionConfigs(GenerativeQuestionServiceRestStub): + def __hash__(self): + return hash("ListGenerativeQuestionConfigs") + + __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} + + @classmethod + def _get_unset_required_fields(cls, message_dict): + return { + k: v + for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items() + if k not in message_dict + } + + def __call__( + self, + request: generative_question_service.ListGenerativeQuestionConfigsRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> generative_question_service.ListGenerativeQuestionConfigsResponse: + r"""Call the list generative question + configs method over HTTP. + + Args: + request (~.generative_question_service.ListGenerativeQuestionConfigsRequest): + The request object. Request for ListQuestions method. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + ~.generative_question_service.ListGenerativeQuestionConfigsResponse: + Response for ListQuestions method. + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "get", + "uri": "/v2beta/{parent=projects/*/locations/*/catalogs/*}/generativeQuestions", + }, + ] + request, metadata = self._interceptor.pre_list_generative_question_configs( + request, metadata + ) + pb_request = ( + generative_question_service.ListGenerativeQuestionConfigsRequest.pb( + request + ) + ) + transcoded_request = path_template.transcode(http_options, pb_request) + + uri = transcoded_request["uri"] + method = transcoded_request["method"] + + # Jsonify the query params + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + use_integers_for_enums=True, + ) + ) + query_params.update(self._get_unset_required_fields(query_params)) + + query_params["$alt"] = "json;enum-encoding=int" + + # Send the request + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(self._session, method)( + "{host}{uri}".format(host=self._host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + # Return the response + resp = generative_question_service.ListGenerativeQuestionConfigsResponse() + pb_resp = ( + generative_question_service.ListGenerativeQuestionConfigsResponse.pb( + resp + ) + ) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + resp = self._interceptor.post_list_generative_question_configs(resp) + return resp + + class _UpdateGenerativeQuestionConfig(GenerativeQuestionServiceRestStub): + def __hash__(self): + return hash("UpdateGenerativeQuestionConfig") + + __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} + + @classmethod + def _get_unset_required_fields(cls, message_dict): + return { + k: v + for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items() + if k not in message_dict + } + + def __call__( + self, + request: generative_question_service.UpdateGenerativeQuestionConfigRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> generative_question.GenerativeQuestionConfig: + r"""Call the update generative + question config method over HTTP. + + Args: + request (~.generative_question_service.UpdateGenerativeQuestionConfigRequest): + The request object. Request for + UpdateGenerativeQuestionConfig method. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + ~.generative_question.GenerativeQuestionConfig: + Configuration for a single generated + question. + + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "patch", + "uri": "/v2beta/{generative_question_config.catalog=projects/*/locations/*/catalogs/*}/generativeQuestion", + "body": "generative_question_config", + }, + ] + request, metadata = self._interceptor.pre_update_generative_question_config( + request, metadata + ) + pb_request = ( + generative_question_service.UpdateGenerativeQuestionConfigRequest.pb( + request + ) + ) + transcoded_request = path_template.transcode(http_options, pb_request) + + # Jsonify the request body + + body = json_format.MessageToJson( + transcoded_request["body"], use_integers_for_enums=True + ) + uri = transcoded_request["uri"] + method = transcoded_request["method"] + + # Jsonify the query params + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + use_integers_for_enums=True, + ) + ) + query_params.update(self._get_unset_required_fields(query_params)) + + query_params["$alt"] = "json;enum-encoding=int" + + # Send the request + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(self._session, method)( + "{host}{uri}".format(host=self._host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + data=body, + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + # Return the response + resp = generative_question.GenerativeQuestionConfig() + pb_resp = generative_question.GenerativeQuestionConfig.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + resp = self._interceptor.post_update_generative_question_config(resp) + return resp + + class _UpdateGenerativeQuestionsFeatureConfig(GenerativeQuestionServiceRestStub): + def __hash__(self): + return hash("UpdateGenerativeQuestionsFeatureConfig") + + __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} + + @classmethod + def _get_unset_required_fields(cls, message_dict): + return { + k: v + for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items() + if k not in message_dict + } + + def __call__( + self, + request: generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> generative_question.GenerativeQuestionsFeatureConfig: + r"""Call the update generative + questions feature config method over HTTP. + + Args: + request (~.generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest): + The request object. Request for + UpdateGenerativeQuestionsFeatureConfig + method. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + ~.generative_question.GenerativeQuestionsFeatureConfig: + Configuration for overall generative + question feature state. + + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "patch", + "uri": "/v2beta/{generative_questions_feature_config.catalog=projects/*/locations/*/catalogs/*}/generativeQuestionFeature", + "body": "generative_questions_feature_config", + }, + ] + ( + request, + metadata, + ) = self._interceptor.pre_update_generative_questions_feature_config( + request, metadata + ) + pb_request = generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest.pb( + request + ) + transcoded_request = path_template.transcode(http_options, pb_request) + + # Jsonify the request body + + body = json_format.MessageToJson( + transcoded_request["body"], use_integers_for_enums=True + ) + uri = transcoded_request["uri"] + method = transcoded_request["method"] + + # Jsonify the query params + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + use_integers_for_enums=True, + ) + ) + query_params.update(self._get_unset_required_fields(query_params)) + + query_params["$alt"] = "json;enum-encoding=int" + + # Send the request + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(self._session, method)( + "{host}{uri}".format(host=self._host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + data=body, + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + # Return the response + resp = generative_question.GenerativeQuestionsFeatureConfig() + pb_resp = generative_question.GenerativeQuestionsFeatureConfig.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + resp = self._interceptor.post_update_generative_questions_feature_config( + resp + ) + return resp + + @property + def batch_update_generative_question_configs( + self, + ) -> Callable[ + [generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest], + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse, + ]: + # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here. + # In C++ this would require a dynamic_cast + return self._BatchUpdateGenerativeQuestionConfigs(self._session, self._host, self._interceptor) # type: ignore + + @property + def get_generative_questions_feature_config( + self, + ) -> Callable[ + [generative_question_service.GetGenerativeQuestionsFeatureConfigRequest], + generative_question.GenerativeQuestionsFeatureConfig, + ]: + # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here. + # In C++ this would require a dynamic_cast + return self._GetGenerativeQuestionsFeatureConfig(self._session, self._host, self._interceptor) # type: ignore + + @property + def list_generative_question_configs( + self, + ) -> Callable[ + [generative_question_service.ListGenerativeQuestionConfigsRequest], + generative_question_service.ListGenerativeQuestionConfigsResponse, + ]: + # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here. + # In C++ this would require a dynamic_cast + return self._ListGenerativeQuestionConfigs(self._session, self._host, self._interceptor) # type: ignore + + @property + def update_generative_question_config( + self, + ) -> Callable[ + [generative_question_service.UpdateGenerativeQuestionConfigRequest], + generative_question.GenerativeQuestionConfig, + ]: + # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here. + # In C++ this would require a dynamic_cast + return self._UpdateGenerativeQuestionConfig(self._session, self._host, self._interceptor) # type: ignore + + @property + def update_generative_questions_feature_config( + self, + ) -> Callable[ + [generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest], + generative_question.GenerativeQuestionsFeatureConfig, + ]: + # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here. + # In C++ this would require a dynamic_cast + return self._UpdateGenerativeQuestionsFeatureConfig(self._session, self._host, self._interceptor) # type: ignore + + @property + def get_operation(self): + return self._GetOperation(self._session, self._host, self._interceptor) # type: ignore + + class _GetOperation(GenerativeQuestionServiceRestStub): + def __call__( + self, + request: operations_pb2.GetOperationRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operations_pb2.Operation: + r"""Call the get operation method over HTTP. + + Args: + request (operations_pb2.GetOperationRequest): + The request object for GetOperation method. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + operations_pb2.Operation: Response from GetOperation method. + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "get", + "uri": "/v2beta/{name=projects/*/locations/*/catalogs/*/branches/*/operations/*}", + }, + { + "method": "get", + "uri": "/v2beta/{name=projects/*/locations/*/catalogs/*/operations/*}", + }, + { + "method": "get", + "uri": "/v2beta/{name=projects/*/locations/*/operations/*}", + }, + { + "method": "get", + "uri": "/v2beta/{name=projects/*/operations/*}", + }, + ] + + request, metadata = self._interceptor.pre_get_operation(request, metadata) + request_kwargs = json_format.MessageToDict(request) + transcoded_request = path_template.transcode(http_options, **request_kwargs) + + uri = transcoded_request["uri"] + method = transcoded_request["method"] + + # Jsonify the query params + query_params = json.loads(json.dumps(transcoded_request["query_params"])) + + # Send the request + headers = dict(metadata) + headers["Content-Type"] = "application/json" + + response = getattr(self._session, method)( + "{host}{uri}".format(host=self._host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params), + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + resp = operations_pb2.Operation() + resp = json_format.Parse(response.content.decode("utf-8"), resp) + resp = self._interceptor.post_get_operation(resp) + return resp + + @property + def list_operations(self): + return self._ListOperations(self._session, self._host, self._interceptor) # type: ignore + + class _ListOperations(GenerativeQuestionServiceRestStub): + def __call__( + self, + request: operations_pb2.ListOperationsRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operations_pb2.ListOperationsResponse: + r"""Call the list operations method over HTTP. + + Args: + request (operations_pb2.ListOperationsRequest): + The request object for ListOperations method. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + operations_pb2.ListOperationsResponse: Response from ListOperations method. + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "get", + "uri": "/v2beta/{name=projects/*/locations/*/catalogs/*}/operations", + }, + { + "method": "get", + "uri": "/v2beta/{name=projects/*/locations/*}/operations", + }, + { + "method": "get", + "uri": "/v2beta/{name=projects/*}/operations", + }, + ] + + request, metadata = self._interceptor.pre_list_operations(request, metadata) + request_kwargs = json_format.MessageToDict(request) + transcoded_request = path_template.transcode(http_options, **request_kwargs) + + uri = transcoded_request["uri"] + method = transcoded_request["method"] + + # Jsonify the query params + query_params = json.loads(json.dumps(transcoded_request["query_params"])) + + # Send the request + headers = dict(metadata) + headers["Content-Type"] = "application/json" + + response = getattr(self._session, method)( + "{host}{uri}".format(host=self._host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params), + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + resp = operations_pb2.ListOperationsResponse() + resp = json_format.Parse(response.content.decode("utf-8"), resp) + resp = self._interceptor.post_list_operations(resp) + return resp + + @property + def kind(self) -> str: + return "rest" + + def close(self): + self._session.close() + + +__all__ = ("GenerativeQuestionServiceRestTransport",) diff --git a/packages/google-cloud-retail/google/cloud/retail_v2beta/services/product_service/async_client.py b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/product_service/async_client.py index 9b1c75f0ae6d..017ddd600ec6 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2beta/services/product_service/async_client.py +++ b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/product_service/async_client.py @@ -52,8 +52,8 @@ from google.protobuf import wrappers_pb2 # type: ignore from google.cloud.retail_v2beta.services.product_service import pagers +from google.cloud.retail_v2beta.types import common, export_config, import_config from google.cloud.retail_v2beta.types import product_service, promotion, purge_config -from google.cloud.retail_v2beta.types import common, import_config from google.cloud.retail_v2beta.types import product from google.cloud.retail_v2beta.types import product as gcr_product @@ -1162,6 +1162,110 @@ async def sample_import_products(): # Done; return the response. return response + async def export_products( + self, + request: Optional[Union[export_config.ExportProductsRequest, dict]] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operation_async.AsyncOperation: + r"""Exports multiple [Product][google.cloud.retail.v2beta.Product]s. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import retail_v2beta + + async def sample_export_products(): + # Create a client + client = retail_v2beta.ProductServiceAsyncClient() + + # Initialize request argument(s) + output_config = retail_v2beta.OutputConfig() + output_config.gcs_destination.output_uri_prefix = "output_uri_prefix_value" + + request = retail_v2beta.ExportProductsRequest( + parent="parent_value", + output_config=output_config, + ) + + # Make the request + operation = client.export_products(request=request) + + print("Waiting for operation to complete...") + + response = (await operation).result() + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.retail_v2beta.types.ExportProductsRequest, dict]]): + The request object. Request message for ExportProducts + method. + retry (google.api_core.retry_async.AsyncRetry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.api_core.operation_async.AsyncOperation: + An object representing a long-running operation. + + The result type for the operation will be :class:`google.cloud.retail_v2beta.types.ExportProductsResponse` Response of the ExportProductsRequest. If the long running + operation is done, then this message is returned by + the google.longrunning.Operations.response field if + the operation was successful. + + """ + # Create or coerce a protobuf request object. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, export_config.ExportProductsRequest): + request = export_config.ExportProductsRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.export_products + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Wrap the response in an operation future. + response = operation_async.from_gapic( + response, + self._client._transport.operations_client, + export_config.ExportProductsResponse, + metadata_type=export_config.ExportMetadata, + ) + + # Done; return the response. + return response + async def set_inventory( self, request: Optional[Union[product_service.SetInventoryRequest, dict]] = None, diff --git a/packages/google-cloud-retail/google/cloud/retail_v2beta/services/product_service/client.py b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/product_service/client.py index 99484158b296..2962e1a264c0 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2beta/services/product_service/client.py +++ b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/product_service/client.py @@ -58,8 +58,8 @@ from google.protobuf import wrappers_pb2 # type: ignore from google.cloud.retail_v2beta.services.product_service import pagers +from google.cloud.retail_v2beta.types import common, export_config, import_config from google.cloud.retail_v2beta.types import product_service, promotion, purge_config -from google.cloud.retail_v2beta.types import common, import_config from google.cloud.retail_v2beta.types import product from google.cloud.retail_v2beta.types import product as gcr_product @@ -1592,6 +1592,108 @@ def sample_import_products(): # Done; return the response. return response + def export_products( + self, + request: Optional[Union[export_config.ExportProductsRequest, dict]] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operation.Operation: + r"""Exports multiple [Product][google.cloud.retail.v2beta.Product]s. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import retail_v2beta + + def sample_export_products(): + # Create a client + client = retail_v2beta.ProductServiceClient() + + # Initialize request argument(s) + output_config = retail_v2beta.OutputConfig() + output_config.gcs_destination.output_uri_prefix = "output_uri_prefix_value" + + request = retail_v2beta.ExportProductsRequest( + parent="parent_value", + output_config=output_config, + ) + + # Make the request + operation = client.export_products(request=request) + + print("Waiting for operation to complete...") + + response = operation.result() + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.retail_v2beta.types.ExportProductsRequest, dict]): + The request object. Request message for ExportProducts + method. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.api_core.operation.Operation: + An object representing a long-running operation. + + The result type for the operation will be :class:`google.cloud.retail_v2beta.types.ExportProductsResponse` Response of the ExportProductsRequest. If the long running + operation is done, then this message is returned by + the google.longrunning.Operations.response field if + the operation was successful. + + """ + # Create or coerce a protobuf request object. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, export_config.ExportProductsRequest): + request = export_config.ExportProductsRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.export_products] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Wrap the response in an operation future. + response = operation.from_gapic( + response, + self._transport.operations_client, + export_config.ExportProductsResponse, + metadata_type=export_config.ExportMetadata, + ) + + # Done; return the response. + return response + def set_inventory( self, request: Optional[Union[product_service.SetInventoryRequest, dict]] = None, diff --git a/packages/google-cloud-retail/google/cloud/retail_v2beta/services/product_service/transports/base.py b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/product_service/transports/base.py index 84548b0b8427..e9bced2f92d2 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2beta/services/product_service/transports/base.py +++ b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/product_service/transports/base.py @@ -28,7 +28,7 @@ from google.protobuf import empty_pb2 # type: ignore from google.cloud.retail_v2beta import gapic_version as package_version -from google.cloud.retail_v2beta.types import import_config +from google.cloud.retail_v2beta.types import export_config, import_config from google.cloud.retail_v2beta.types import product from google.cloud.retail_v2beta.types import product as gcr_product from google.cloud.retail_v2beta.types import product_service, purge_config @@ -179,6 +179,11 @@ def _prep_wrapped_messages(self, client_info): default_timeout=300.0, client_info=client_info, ), + self.export_products: gapic_v1.method.wrap_method( + self.export_products, + default_timeout=None, + client_info=client_info, + ), self.set_inventory: gapic_v1.method.wrap_method( self.set_inventory, default_timeout=None, @@ -286,6 +291,15 @@ def import_products( ]: raise NotImplementedError() + @property + def export_products( + self, + ) -> Callable[ + [export_config.ExportProductsRequest], + Union[operations_pb2.Operation, Awaitable[operations_pb2.Operation]], + ]: + raise NotImplementedError() + @property def set_inventory( self, diff --git a/packages/google-cloud-retail/google/cloud/retail_v2beta/services/product_service/transports/grpc.py b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/product_service/transports/grpc.py index a420a27eda76..18b23ec3c839 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2beta/services/product_service/transports/grpc.py +++ b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/product_service/transports/grpc.py @@ -25,7 +25,7 @@ from google.protobuf import empty_pb2 # type: ignore import grpc # type: ignore -from google.cloud.retail_v2beta.types import import_config +from google.cloud.retail_v2beta.types import export_config, import_config from google.cloud.retail_v2beta.types import product from google.cloud.retail_v2beta.types import product as gcr_product from google.cloud.retail_v2beta.types import product_service, purge_config @@ -467,6 +467,32 @@ def import_products( ) return self._stubs["import_products"] + @property + def export_products( + self, + ) -> Callable[[export_config.ExportProductsRequest], operations_pb2.Operation]: + r"""Return a callable for the export products method over gRPC. + + Exports multiple [Product][google.cloud.retail.v2beta.Product]s. + + Returns: + Callable[[~.ExportProductsRequest], + ~.Operation]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "export_products" not in self._stubs: + self._stubs["export_products"] = self.grpc_channel.unary_unary( + "/google.cloud.retail.v2beta.ProductService/ExportProducts", + request_serializer=export_config.ExportProductsRequest.serialize, + response_deserializer=operations_pb2.Operation.FromString, + ) + return self._stubs["export_products"] + @property def set_inventory( self, diff --git a/packages/google-cloud-retail/google/cloud/retail_v2beta/services/product_service/transports/grpc_asyncio.py b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/product_service/transports/grpc_asyncio.py index 05db1a637b87..12a79e862403 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2beta/services/product_service/transports/grpc_asyncio.py +++ b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/product_service/transports/grpc_asyncio.py @@ -27,7 +27,7 @@ import grpc # type: ignore from grpc.experimental import aio # type: ignore -from google.cloud.retail_v2beta.types import import_config +from google.cloud.retail_v2beta.types import export_config, import_config from google.cloud.retail_v2beta.types import product from google.cloud.retail_v2beta.types import product as gcr_product from google.cloud.retail_v2beta.types import product_service, purge_config @@ -482,6 +482,34 @@ def import_products( ) return self._stubs["import_products"] + @property + def export_products( + self, + ) -> Callable[ + [export_config.ExportProductsRequest], Awaitable[operations_pb2.Operation] + ]: + r"""Return a callable for the export products method over gRPC. + + Exports multiple [Product][google.cloud.retail.v2beta.Product]s. + + Returns: + Callable[[~.ExportProductsRequest], + Awaitable[~.Operation]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "export_products" not in self._stubs: + self._stubs["export_products"] = self.grpc_channel.unary_unary( + "/google.cloud.retail.v2beta.ProductService/ExportProducts", + request_serializer=export_config.ExportProductsRequest.serialize, + response_deserializer=operations_pb2.Operation.FromString, + ) + return self._stubs["export_products"] + @property def set_inventory( self, @@ -847,6 +875,11 @@ def _prep_wrapped_messages(self, client_info): default_timeout=300.0, client_info=client_info, ), + self.export_products: gapic_v1.method_async.wrap_method( + self.export_products, + default_timeout=None, + client_info=client_info, + ), self.set_inventory: gapic_v1.method_async.wrap_method( self.set_inventory, default_timeout=None, diff --git a/packages/google-cloud-retail/google/cloud/retail_v2beta/services/product_service/transports/rest.py b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/product_service/transports/rest.py index 3361abecf7eb..ca1e9a50d73b 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2beta/services/product_service/transports/rest.py +++ b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/product_service/transports/rest.py @@ -46,7 +46,7 @@ from google.longrunning import operations_pb2 # type: ignore from google.protobuf import empty_pb2 # type: ignore -from google.cloud.retail_v2beta.types import import_config +from google.cloud.retail_v2beta.types import export_config, import_config from google.cloud.retail_v2beta.types import product from google.cloud.retail_v2beta.types import product as gcr_product from google.cloud.retail_v2beta.types import product_service, purge_config @@ -104,6 +104,14 @@ def pre_delete_product(self, request, metadata): logging.log(f"Received request: {request}") return request, metadata + def pre_export_products(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_export_products(self, response): + logging.log(f"Received response: {response}") + return response + def pre_get_product(self, request, metadata): logging.log(f"Received request: {request}") return request, metadata @@ -253,6 +261,29 @@ def pre_delete_product( """ return request, metadata + def pre_export_products( + self, + request: export_config.ExportProductsRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[export_config.ExportProductsRequest, Sequence[Tuple[str, str]]]: + """Pre-rpc interceptor for export_products + + Override in a subclass to manipulate the request or metadata + before they are sent to the ProductService server. + """ + return request, metadata + + def post_export_products( + self, response: operations_pb2.Operation + ) -> operations_pb2.Operation: + """Post-rpc interceptor for export_products + + Override in a subclass to manipulate the response + after it is returned by the ProductService server but before + it is returned to user code. + """ + return response + def pre_get_product( self, request: product_service.GetProductRequest, @@ -1010,6 +1041,100 @@ def __call__( if response.status_code >= 400: raise core_exceptions.from_http_response(response) + class _ExportProducts(ProductServiceRestStub): + def __hash__(self): + return hash("ExportProducts") + + __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} + + @classmethod + def _get_unset_required_fields(cls, message_dict): + return { + k: v + for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items() + if k not in message_dict + } + + def __call__( + self, + request: export_config.ExportProductsRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operations_pb2.Operation: + r"""Call the export products method over HTTP. + + Args: + request (~.export_config.ExportProductsRequest): + The request object. Request message for ExportProducts + method. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + ~.operations_pb2.Operation: + This resource represents a + long-running operation that is the + result of a network API call. + + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "post", + "uri": "/v2beta/{parent=projects/*/locations/*/catalogs/*/branches/*}/products:export", + "body": "*", + }, + ] + request, metadata = self._interceptor.pre_export_products(request, metadata) + pb_request = export_config.ExportProductsRequest.pb(request) + transcoded_request = path_template.transcode(http_options, pb_request) + + # Jsonify the request body + + body = json_format.MessageToJson( + transcoded_request["body"], use_integers_for_enums=True + ) + uri = transcoded_request["uri"] + method = transcoded_request["method"] + + # Jsonify the query params + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + use_integers_for_enums=True, + ) + ) + query_params.update(self._get_unset_required_fields(query_params)) + + query_params["$alt"] = "json;enum-encoding=int" + + # Send the request + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(self._session, method)( + "{host}{uri}".format(host=self._host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + data=body, + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + # Return the response + resp = operations_pb2.Operation() + json_format.Parse(response.content, resp, ignore_unknown_fields=True) + resp = self._interceptor.post_export_products(resp) + return resp + class _GetProduct(ProductServiceRestStub): def __hash__(self): return hash("GetProduct") @@ -1799,6 +1924,14 @@ def delete_product( # In C++ this would require a dynamic_cast return self._DeleteProduct(self._session, self._host, self._interceptor) # type: ignore + @property + def export_products( + self, + ) -> Callable[[export_config.ExportProductsRequest], operations_pb2.Operation]: + # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here. + # In C++ this would require a dynamic_cast + return self._ExportProducts(self._session, self._host, self._interceptor) # type: ignore + @property def get_product( self, diff --git a/packages/google-cloud-retail/google/cloud/retail_v2beta/services/project_service/__init__.py b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/project_service/__init__.py new file mode 100644 index 000000000000..245aea0dfd81 --- /dev/null +++ b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/project_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from .async_client import ProjectServiceAsyncClient +from .client import ProjectServiceClient + +__all__ = ( + "ProjectServiceClient", + "ProjectServiceAsyncClient", +) diff --git a/packages/google-cloud-retail/google/cloud/retail_v2beta/services/project_service/async_client.py b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/project_service/async_client.py new file mode 100644 index 000000000000..5aa25fa7f33a --- /dev/null +++ b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/project_service/async_client.py @@ -0,0 +1,622 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import re +from typing import ( + Callable, + Dict, + Mapping, + MutableMapping, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, +) + +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry_async as retries +from google.api_core.client_options import ClientOptions +from google.auth import credentials as ga_credentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.cloud.retail_v2beta import gapic_version as package_version + +try: + OptionalRetry = Union[retries.AsyncRetry, gapic_v1.method._MethodDefault, None] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.AsyncRetry, object, None] # type: ignore + +from google.cloud.location import locations_pb2 # type: ignore +from google.longrunning import operations_pb2 # type: ignore +from google.protobuf import field_mask_pb2 # type: ignore + +from google.cloud.retail_v2beta.types import project, project_service + +from .client import ProjectServiceClient +from .transports.base import DEFAULT_CLIENT_INFO, ProjectServiceTransport +from .transports.grpc_asyncio import ProjectServiceGrpcAsyncIOTransport + + +class ProjectServiceAsyncClient: + """Service for settings at Project level.""" + + _client: ProjectServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = ProjectServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = ProjectServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ProjectServiceClient._DEFAULT_ENDPOINT_TEMPLATE + _DEFAULT_UNIVERSE = ProjectServiceClient._DEFAULT_UNIVERSE + + alert_config_path = staticmethod(ProjectServiceClient.alert_config_path) + parse_alert_config_path = staticmethod(ProjectServiceClient.parse_alert_config_path) + common_billing_account_path = staticmethod( + ProjectServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + ProjectServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod(ProjectServiceClient.common_folder_path) + parse_common_folder_path = staticmethod( + ProjectServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + ProjectServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + ProjectServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod(ProjectServiceClient.common_project_path) + parse_common_project_path = staticmethod( + ProjectServiceClient.parse_common_project_path + ) + common_location_path = staticmethod(ProjectServiceClient.common_location_path) + parse_common_location_path = staticmethod( + ProjectServiceClient.parse_common_location_path + ) + + @classmethod + def from_service_account_info(cls, info: dict, *args, **kwargs): + """Creates an instance of this client using the provided credentials + info. + + Args: + info (dict): The service account private key info. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + ProjectServiceAsyncClient: The constructed client. + """ + return ProjectServiceClient.from_service_account_info.__func__(ProjectServiceAsyncClient, info, *args, **kwargs) # type: ignore + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + ProjectServiceAsyncClient: The constructed client. + """ + return ProjectServiceClient.from_service_account_file.__func__(ProjectServiceAsyncClient, filename, *args, **kwargs) # type: ignore + + from_service_account_json = from_service_account_file + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[ClientOptions] = None + ): + """Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + return ProjectServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> ProjectServiceTransport: + """Returns the transport used by the client instance. + + Returns: + ProjectServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._client._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used + by the client instance. + """ + return self._client._universe_domain + + get_transport_class = ProjectServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, ProjectServiceTransport, Callable[..., ProjectServiceTransport]] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the project service async client. + + Args: + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + transport (Optional[Union[str,ProjectServiceTransport,Callable[..., ProjectServiceTransport]]]): + The transport to use, or a Callable that constructs and returns a new transport to use. + If a Callable is given, it will be called with the same set of initialization + arguments as used in the ProjectServiceTransport constructor. + If set to None, a transport is chosen automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): + Custom options for the client. + + 1. The ``api_endpoint`` property can be used to override the + default endpoint provided by the client when ``transport`` is + not explicitly provided. Only if this property is not set and + ``transport`` was not explicitly provided, the endpoint is + determined by the GOOGLE_API_USE_MTLS_ENDPOINT environment + variable, which have one of the following values: + "always" (always use the default mTLS endpoint), "never" (always + use the default regular endpoint) and "auto" (auto-switch to the + default mTLS endpoint if client certificate is present; this is + the default value). + + 2. If the GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide a client certificate for mTLS transport. If + not provided, the default SSL client certificate will be used if + present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not + set, no client certificate will be used. + + 3. The ``universe_domain`` property can be used to override the + default "googleapis.com" universe. Note that ``api_endpoint`` + property still takes precedence; and ``universe_domain`` is + currently not supported for mTLS. + + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + + Raises: + google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport + creation failed for any reason. + """ + self._client = ProjectServiceClient( + credentials=credentials, + transport=transport, + client_options=client_options, + client_info=client_info, + ) + + async def get_alert_config( + self, + request: Optional[Union[project_service.GetAlertConfigRequest, dict]] = None, + *, + name: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> project.AlertConfig: + r"""Get the [AlertConfig][google.cloud.retail.v2beta.AlertConfig] of + the requested project. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import retail_v2beta + + async def sample_get_alert_config(): + # Create a client + client = retail_v2beta.ProjectServiceAsyncClient() + + # Initialize request argument(s) + request = retail_v2beta.GetAlertConfigRequest( + name="name_value", + ) + + # Make the request + response = await client.get_alert_config(request=request) + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.retail_v2beta.types.GetAlertConfigRequest, dict]]): + The request object. Request for + [ProjectService.GetAlertConfig][google.cloud.retail.v2beta.ProjectService.GetAlertConfig] + method. + name (:class:`str`): + Required. Full AlertConfig resource name. Format: + projects/{project_number}/alertConfig + + This corresponds to the ``name`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry_async.AsyncRetry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.retail_v2beta.types.AlertConfig: + Project level alert config. + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([name]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, project_service.GetAlertConfigRequest): + request = project_service.GetAlertConfigRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if name is not None: + request.name = name + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.get_alert_config + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def update_alert_config( + self, + request: Optional[Union[project_service.UpdateAlertConfigRequest, dict]] = None, + *, + alert_config: Optional[project.AlertConfig] = None, + update_mask: Optional[field_mask_pb2.FieldMask] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> project.AlertConfig: + r"""Update the alert config of the requested project. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import retail_v2beta + + async def sample_update_alert_config(): + # Create a client + client = retail_v2beta.ProjectServiceAsyncClient() + + # Initialize request argument(s) + alert_config = retail_v2beta.AlertConfig() + alert_config.name = "name_value" + + request = retail_v2beta.UpdateAlertConfigRequest( + alert_config=alert_config, + ) + + # Make the request + response = await client.update_alert_config(request=request) + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.retail_v2beta.types.UpdateAlertConfigRequest, dict]]): + The request object. Request for + [ProjectService.UpdateAlertConfig][google.cloud.retail.v2beta.ProjectService.UpdateAlertConfig] + method. + alert_config (:class:`google.cloud.retail_v2beta.types.AlertConfig`): + Required. The + [AlertConfig][google.cloud.retail.v2beta.AlertConfig] to + update. + + If the caller does not have permission to update the + [AlertConfig][google.cloud.retail.v2beta.AlertConfig], + then a PERMISSION_DENIED error is returned. + + If the + [AlertConfig][google.cloud.retail.v2beta.AlertConfig] to + update does not exist, a NOT_FOUND error is returned. + + This corresponds to the ``alert_config`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + update_mask (:class:`google.protobuf.field_mask_pb2.FieldMask`): + Indicates which fields in the provided + [AlertConfig][google.cloud.retail.v2beta.AlertConfig] to + update. If not set, all supported fields are updated. + + This corresponds to the ``update_mask`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry_async.AsyncRetry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.retail_v2beta.types.AlertConfig: + Project level alert config. + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([alert_config, update_mask]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, project_service.UpdateAlertConfigRequest): + request = project_service.UpdateAlertConfigRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if alert_config is not None: + request.alert_config = alert_config + if update_mask is not None: + request.update_mask = update_mask + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.update_alert_config + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("alert_config.name", request.alert_config.name),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def list_operations( + self, + request: Optional[operations_pb2.ListOperationsRequest] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operations_pb2.ListOperationsResponse: + r"""Lists operations that match the specified filter in the request. + + Args: + request (:class:`~.operations_pb2.ListOperationsRequest`): + The request object. Request message for + `ListOperations` method. + retry (google.api_core.retry_async.AsyncRetry): Designation of what errors, + if any, should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + Returns: + ~.operations_pb2.ListOperationsResponse: + Response message for ``ListOperations`` method. + """ + # Create or coerce a protobuf request object. + # The request isn't a proto-plus wrapped type, + # so it must be constructed via keyword expansion. + if isinstance(request, dict): + request = operations_pb2.ListOperationsRequest(**request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method_async.wrap_method( + self._client._transport.list_operations, + default_timeout=None, + client_info=DEFAULT_CLIENT_INFO, + ) + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def get_operation( + self, + request: Optional[operations_pb2.GetOperationRequest] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operations_pb2.Operation: + r"""Gets the latest state of a long-running operation. + + Args: + request (:class:`~.operations_pb2.GetOperationRequest`): + The request object. Request message for + `GetOperation` method. + retry (google.api_core.retry_async.AsyncRetry): Designation of what errors, + if any, should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + Returns: + ~.operations_pb2.Operation: + An ``Operation`` object. + """ + # Create or coerce a protobuf request object. + # The request isn't a proto-plus wrapped type, + # so it must be constructed via keyword expansion. + if isinstance(request, dict): + request = operations_pb2.GetOperationRequest(**request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method_async.wrap_method( + self._client._transport.get_operation, + default_timeout=None, + client_info=DEFAULT_CLIENT_INFO, + ) + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def __aenter__(self) -> "ProjectServiceAsyncClient": + return self + + async def __aexit__(self, exc_type, exc, tb): + await self.transport.close() + + +DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=package_version.__version__ +) + + +__all__ = ("ProjectServiceAsyncClient",) diff --git a/packages/google-cloud-retail/google/cloud/retail_v2beta/services/project_service/client.py b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/project_service/client.py new file mode 100644 index 000000000000..57792ef42493 --- /dev/null +++ b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/project_service/client.py @@ -0,0 +1,1039 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +import os +import re +from typing import ( + Callable, + Dict, + Mapping, + MutableMapping, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) +import warnings + +from google.api_core import client_options as client_options_lib +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.exceptions import MutualTLSChannelError # type: ignore +from google.auth.transport import mtls # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.cloud.retail_v2beta import gapic_version as package_version + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault, None] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object, None] # type: ignore + +from google.cloud.location import locations_pb2 # type: ignore +from google.longrunning import operations_pb2 # type: ignore +from google.protobuf import field_mask_pb2 # type: ignore + +from google.cloud.retail_v2beta.types import project, project_service + +from .transports.base import DEFAULT_CLIENT_INFO, ProjectServiceTransport +from .transports.grpc import ProjectServiceGrpcTransport +from .transports.grpc_asyncio import ProjectServiceGrpcAsyncIOTransport +from .transports.rest import ProjectServiceRestTransport + + +class ProjectServiceClientMeta(type): + """Metaclass for the ProjectService client. + + This provides class-level methods for building and retrieving + support objects (e.g. transport) without polluting the client instance + objects. + """ + + _transport_registry = ( + OrderedDict() + ) # type: Dict[str, Type[ProjectServiceTransport]] + _transport_registry["grpc"] = ProjectServiceGrpcTransport + _transport_registry["grpc_asyncio"] = ProjectServiceGrpcAsyncIOTransport + _transport_registry["rest"] = ProjectServiceRestTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[ProjectServiceTransport]: + """Returns an appropriate transport class. + + Args: + label: The name of the desired transport. If none is + provided, then the first transport in the registry is used. + + Returns: + The transport class to use. + """ + # If a specific transport is requested, return that one. + if label: + return cls._transport_registry[label] + + # No transport is requested; return the default (that is, the first one + # in the dictionary). + return next(iter(cls._transport_registry.values())) + + +class ProjectServiceClient(metaclass=ProjectServiceClientMeta): + """Service for settings at Project level.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint): + """Converts api endpoint to mTLS endpoint. + + Convert "*.sandbox.googleapis.com" and "*.googleapis.com" to + "*.mtls.sandbox.googleapis.com" and "*.mtls.googleapis.com" respectively. + Args: + api_endpoint (Optional[str]): the api endpoint to convert. + Returns: + str: converted mTLS api endpoint. + """ + if not api_endpoint: + return api_endpoint + + mtls_endpoint_re = re.compile( + r"(?P[^.]+)(?P\.mtls)?(?P\.sandbox)?(?P\.googleapis\.com)?" + ) + + m = mtls_endpoint_re.match(api_endpoint) + name, mtls, sandbox, googledomain = m.groups() + if mtls or not googledomain: + return api_endpoint + + if sandbox: + return api_endpoint.replace( + "sandbox.googleapis.com", "mtls.sandbox.googleapis.com" + ) + + return api_endpoint.replace(".googleapis.com", ".mtls.googleapis.com") + + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = "retail.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "retail.{UNIVERSE_DOMAIN}" + _DEFAULT_UNIVERSE = "googleapis.com" + + @classmethod + def from_service_account_info(cls, info: dict, *args, **kwargs): + """Creates an instance of this client using the provided credentials + info. + + Args: + info (dict): The service account private key info. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + ProjectServiceClient: The constructed client. + """ + credentials = service_account.Credentials.from_service_account_info(info) + kwargs["credentials"] = credentials + return cls(*args, **kwargs) + + @classmethod + def from_service_account_file(cls, filename: str, *args, **kwargs): + """Creates an instance of this client using the provided credentials + file. + + Args: + filename (str): The path to the service account private key json + file. + args: Additional arguments to pass to the constructor. + kwargs: Additional arguments to pass to the constructor. + + Returns: + ProjectServiceClient: The constructed client. + """ + credentials = service_account.Credentials.from_service_account_file(filename) + kwargs["credentials"] = credentials + return cls(*args, **kwargs) + + from_service_account_json = from_service_account_file + + @property + def transport(self) -> ProjectServiceTransport: + """Returns the transport used by the client instance. + + Returns: + ProjectServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def alert_config_path( + project: str, + ) -> str: + """Returns a fully-qualified alert_config string.""" + return "projects/{project}/alertConfig".format( + project=project, + ) + + @staticmethod + def parse_alert_config_path(path: str) -> Dict[str, str]: + """Parses a alert_config path into its component segments.""" + m = re.match(r"^projects/(?P.+?)/alertConfig$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_billing_account_path( + billing_account: str, + ) -> str: + """Returns a fully-qualified billing_account string.""" + return "billingAccounts/{billing_account}".format( + billing_account=billing_account, + ) + + @staticmethod + def parse_common_billing_account_path(path: str) -> Dict[str, str]: + """Parse a billing_account path into its component segments.""" + m = re.match(r"^billingAccounts/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_folder_path( + folder: str, + ) -> str: + """Returns a fully-qualified folder string.""" + return "folders/{folder}".format( + folder=folder, + ) + + @staticmethod + def parse_common_folder_path(path: str) -> Dict[str, str]: + """Parse a folder path into its component segments.""" + m = re.match(r"^folders/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_organization_path( + organization: str, + ) -> str: + """Returns a fully-qualified organization string.""" + return "organizations/{organization}".format( + organization=organization, + ) + + @staticmethod + def parse_common_organization_path(path: str) -> Dict[str, str]: + """Parse a organization path into its component segments.""" + m = re.match(r"^organizations/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_project_path( + project: str, + ) -> str: + """Returns a fully-qualified project string.""" + return "projects/{project}".format( + project=project, + ) + + @staticmethod + def parse_common_project_path(path: str) -> Dict[str, str]: + """Parse a project path into its component segments.""" + m = re.match(r"^projects/(?P.+?)$", path) + return m.groupdict() if m else {} + + @staticmethod + def common_location_path( + project: str, + location: str, + ) -> str: + """Returns a fully-qualified location string.""" + return "projects/{project}/locations/{location}".format( + project=project, + location=location, + ) + + @staticmethod + def parse_common_location_path(path: str) -> Dict[str, str]: + """Parse a location path into its component segments.""" + m = re.match(r"^projects/(?P.+?)/locations/(?P.+?)$", path) + return m.groupdict() if m else {} + + @classmethod + def get_mtls_endpoint_and_cert_source( + cls, client_options: Optional[client_options_lib.ClientOptions] = None + ): + """Deprecated. Return the API endpoint and client cert source for mutual TLS. + + The client cert source is determined in the following order: + (1) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not "true", the + client cert source is None. + (2) if `client_options.client_cert_source` is provided, use the provided one; if the + default client cert source exists, use the default one; otherwise the client cert + source is None. + + The API endpoint is determined in the following order: + (1) if `client_options.api_endpoint` if provided, use the provided one. + (2) if `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is "always", use the + default mTLS endpoint; if the environment variable is "never", use the default API + endpoint; otherwise if client cert source exists, use the default mTLS endpoint, otherwise + use the default API endpoint. + + More details can be found at https://google.aip.dev/auth/4114. + + Args: + client_options (google.api_core.client_options.ClientOptions): Custom options for the + client. Only the `api_endpoint` and `client_cert_source` properties may be used + in this method. + + Returns: + Tuple[str, Callable[[], Tuple[bytes, bytes]]]: returns the API endpoint and the + client cert source to use. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If any errors happen. + """ + + warnings.warn( + "get_mtls_endpoint_and_cert_source is deprecated. Use the api_endpoint property instead.", + DeprecationWarning, + ) + if client_options is None: + client_options = client_options_lib.ClientOptions() + use_client_cert = os.getenv("GOOGLE_API_USE_CLIENT_CERTIFICATE", "false") + use_mtls_endpoint = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + if use_client_cert not in ("true", "false"): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + if use_mtls_endpoint not in ("auto", "never", "always"): + raise MutualTLSChannelError( + "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`" + ) + + # Figure out the client cert source to use. + client_cert_source = None + if use_client_cert == "true": + if client_options.client_cert_source: + client_cert_source = client_options.client_cert_source + elif mtls.has_default_client_cert_source(): + client_cert_source = mtls.default_client_cert_source() + + # Figure out which api endpoint to use. + if client_options.api_endpoint is not None: + api_endpoint = client_options.api_endpoint + elif use_mtls_endpoint == "always" or ( + use_mtls_endpoint == "auto" and client_cert_source + ): + api_endpoint = cls.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = cls.DEFAULT_ENDPOINT + + return api_endpoint, client_cert_source + + @staticmethod + def _read_environment_variables(): + """Returns the environment variables used by the client. + + Returns: + Tuple[bool, str, str]: returns the GOOGLE_API_USE_CLIENT_CERTIFICATE, + GOOGLE_API_USE_MTLS_ENDPOINT, and GOOGLE_CLOUD_UNIVERSE_DOMAIN environment variables. + + Raises: + ValueError: If GOOGLE_API_USE_CLIENT_CERTIFICATE is not + any of ["true", "false"]. + google.auth.exceptions.MutualTLSChannelError: If GOOGLE_API_USE_MTLS_ENDPOINT + is not any of ["auto", "never", "always"]. + """ + use_client_cert = os.getenv( + "GOOGLE_API_USE_CLIENT_CERTIFICATE", "false" + ).lower() + use_mtls_endpoint = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto").lower() + universe_domain_env = os.getenv("GOOGLE_CLOUD_UNIVERSE_DOMAIN") + if use_client_cert not in ("true", "false"): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + if use_mtls_endpoint not in ("auto", "never", "always"): + raise MutualTLSChannelError( + "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`" + ) + return use_client_cert == "true", use_mtls_endpoint, universe_domain_env + + @staticmethod + def _get_client_cert_source(provided_cert_source, use_cert_flag): + """Return the client cert source to be used by the client. + + Args: + provided_cert_source (bytes): The client certificate source provided. + use_cert_flag (bool): A flag indicating whether to use the client certificate. + + Returns: + bytes or None: The client cert source to be used by the client. + """ + client_cert_source = None + if use_cert_flag: + if provided_cert_source: + client_cert_source = provided_cert_source + elif mtls.has_default_client_cert_source(): + client_cert_source = mtls.default_client_cert_source() + return client_cert_source + + @staticmethod + def _get_api_endpoint( + api_override, client_cert_source, universe_domain, use_mtls_endpoint + ): + """Return the API endpoint used by the client. + + Args: + api_override (str): The API endpoint override. If specified, this is always + the return value of this function and the other arguments are not used. + client_cert_source (bytes): The client certificate source used by the client. + universe_domain (str): The universe domain used by the client. + use_mtls_endpoint (str): How to use the mTLS endpoint, which depends also on the other parameters. + Possible values are "always", "auto", or "never". + + Returns: + str: The API endpoint to be used by the client. + """ + if api_override is not None: + api_endpoint = api_override + elif use_mtls_endpoint == "always" or ( + use_mtls_endpoint == "auto" and client_cert_source + ): + _default_universe = ProjectServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = ProjectServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ProjectServiceClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=universe_domain + ) + return api_endpoint + + @staticmethod + def _get_universe_domain( + client_universe_domain: Optional[str], universe_domain_env: Optional[str] + ) -> str: + """Return the universe domain used by the client. + + Args: + client_universe_domain (Optional[str]): The universe domain configured via the client options. + universe_domain_env (Optional[str]): The universe domain configured via the "GOOGLE_CLOUD_UNIVERSE_DOMAIN" environment variable. + + Returns: + str: The universe domain to be used by the client. + + Raises: + ValueError: If the universe domain is an empty string. + """ + universe_domain = ProjectServiceClient._DEFAULT_UNIVERSE + if client_universe_domain is not None: + universe_domain = client_universe_domain + elif universe_domain_env is not None: + universe_domain = universe_domain_env + if len(universe_domain.strip()) == 0: + raise ValueError("Universe Domain cannot be an empty string.") + return universe_domain + + @staticmethod + def _compare_universes( + client_universe: str, credentials: ga_credentials.Credentials + ) -> bool: + """Returns True iff the universe domains used by the client and credentials match. + + Args: + client_universe (str): The universe domain configured via the client options. + credentials (ga_credentials.Credentials): The credentials being used in the client. + + Returns: + bool: True iff client_universe matches the universe in credentials. + + Raises: + ValueError: when client_universe does not match the universe in credentials. + """ + + default_universe = ProjectServiceClient._DEFAULT_UNIVERSE + credentials_universe = getattr(credentials, "universe_domain", default_universe) + + if client_universe != credentials_universe: + raise ValueError( + "The configured universe domain " + f"({client_universe}) does not match the universe domain " + f"found in the credentials ({credentials_universe}). " + "If you haven't configured the universe domain explicitly, " + f"`{default_universe}` is the default." + ) + return True + + def _validate_universe_domain(self): + """Validates client's and credentials' universe domains are consistent. + + Returns: + bool: True iff the configured universe domain is valid. + + Raises: + ValueError: If the configured universe domain is not valid. + """ + self._is_universe_domain_valid = ( + self._is_universe_domain_valid + or ProjectServiceClient._compare_universes( + self.universe_domain, self.transport._credentials + ) + ) + return self._is_universe_domain_valid + + @property + def api_endpoint(self): + """Return the API endpoint used by the client instance. + + Returns: + str: The API endpoint used by the client instance. + """ + return self._api_endpoint + + @property + def universe_domain(self) -> str: + """Return the universe domain used by the client instance. + + Returns: + str: The universe domain used by the client instance. + """ + return self._universe_domain + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[str, ProjectServiceTransport, Callable[..., ProjectServiceTransport]] + ] = None, + client_options: Optional[Union[client_options_lib.ClientOptions, dict]] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the project service client. + + Args: + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + transport (Optional[Union[str,ProjectServiceTransport,Callable[..., ProjectServiceTransport]]]): + The transport to use, or a Callable that constructs and returns a new transport. + If a Callable is given, it will be called with the same set of initialization + arguments as used in the ProjectServiceTransport constructor. + If set to None, a transport is chosen automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): + Custom options for the client. + + 1. The ``api_endpoint`` property can be used to override the + default endpoint provided by the client when ``transport`` is + not explicitly provided. Only if this property is not set and + ``transport`` was not explicitly provided, the endpoint is + determined by the GOOGLE_API_USE_MTLS_ENDPOINT environment + variable, which have one of the following values: + "always" (always use the default mTLS endpoint), "never" (always + use the default regular endpoint) and "auto" (auto-switch to the + default mTLS endpoint if client certificate is present; this is + the default value). + + 2. If the GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide a client certificate for mTLS transport. If + not provided, the default SSL client certificate will be used if + present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not + set, no client certificate will be used. + + 3. The ``universe_domain`` property can be used to override the + default "googleapis.com" universe. Note that the ``api_endpoint`` + property still takes precedence; and ``universe_domain`` is + currently not supported for mTLS. + + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + """ + self._client_options = client_options + if isinstance(self._client_options, dict): + self._client_options = client_options_lib.from_dict(self._client_options) + if self._client_options is None: + self._client_options = client_options_lib.ClientOptions() + self._client_options = cast( + client_options_lib.ClientOptions, self._client_options + ) + + universe_domain_opt = getattr(self._client_options, "universe_domain", None) + + ( + self._use_client_cert, + self._use_mtls_endpoint, + self._universe_domain_env, + ) = ProjectServiceClient._read_environment_variables() + self._client_cert_source = ProjectServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + self._universe_domain = ProjectServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + self._api_endpoint = None # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + api_key_value = getattr(self._client_options, "api_key", None) + if api_key_value and credentials: + raise ValueError( + "client_options.api_key and credentials are mutually exclusive" + ) + + # Save or instantiate the transport. + # Ordinarily, we provide the transport, but allowing a custom transport + # instance provides an extensibility point for unusual situations. + transport_provided = isinstance(transport, ProjectServiceTransport) + if transport_provided: + # transport is a ProjectServiceTransport instance. + if credentials or self._client_options.credentials_file or api_key_value: + raise ValueError( + "When providing a transport instance, " + "provide its credentials directly." + ) + if self._client_options.scopes: + raise ValueError( + "When providing a transport instance, provide its scopes " + "directly." + ) + self._transport = cast(ProjectServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or ProjectServiceClient._get_api_endpoint( + self._client_options.api_endpoint, + self._client_cert_source, + self._universe_domain, + self._use_mtls_endpoint, + ) + ) + + if not transport_provided: + import google.auth._default # type: ignore + + if api_key_value and hasattr( + google.auth._default, "get_api_key_credentials" + ): + credentials = google.auth._default.get_api_key_credentials( + api_key_value + ) + + transport_init: Union[ + Type[ProjectServiceTransport], Callable[..., ProjectServiceTransport] + ] = ( + ProjectServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast(Callable[..., ProjectServiceTransport], transport) + ) + # initialize with the provided callable or the passed in class + self._transport = transport_init( + credentials=credentials, + credentials_file=self._client_options.credentials_file, + host=self._api_endpoint, + scopes=self._client_options.scopes, + client_cert_source_for_mtls=self._client_cert_source, + quota_project_id=self._client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + api_audience=self._client_options.api_audience, + ) + + def get_alert_config( + self, + request: Optional[Union[project_service.GetAlertConfigRequest, dict]] = None, + *, + name: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> project.AlertConfig: + r"""Get the [AlertConfig][google.cloud.retail.v2beta.AlertConfig] of + the requested project. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import retail_v2beta + + def sample_get_alert_config(): + # Create a client + client = retail_v2beta.ProjectServiceClient() + + # Initialize request argument(s) + request = retail_v2beta.GetAlertConfigRequest( + name="name_value", + ) + + # Make the request + response = client.get_alert_config(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.retail_v2beta.types.GetAlertConfigRequest, dict]): + The request object. Request for + [ProjectService.GetAlertConfig][google.cloud.retail.v2beta.ProjectService.GetAlertConfig] + method. + name (str): + Required. Full AlertConfig resource name. Format: + projects/{project_number}/alertConfig + + This corresponds to the ``name`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.retail_v2beta.types.AlertConfig: + Project level alert config. + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([name]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, project_service.GetAlertConfigRequest): + request = project_service.GetAlertConfigRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if name is not None: + request.name = name + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.get_alert_config] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + def update_alert_config( + self, + request: Optional[Union[project_service.UpdateAlertConfigRequest, dict]] = None, + *, + alert_config: Optional[project.AlertConfig] = None, + update_mask: Optional[field_mask_pb2.FieldMask] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> project.AlertConfig: + r"""Update the alert config of the requested project. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import retail_v2beta + + def sample_update_alert_config(): + # Create a client + client = retail_v2beta.ProjectServiceClient() + + # Initialize request argument(s) + alert_config = retail_v2beta.AlertConfig() + alert_config.name = "name_value" + + request = retail_v2beta.UpdateAlertConfigRequest( + alert_config=alert_config, + ) + + # Make the request + response = client.update_alert_config(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.retail_v2beta.types.UpdateAlertConfigRequest, dict]): + The request object. Request for + [ProjectService.UpdateAlertConfig][google.cloud.retail.v2beta.ProjectService.UpdateAlertConfig] + method. + alert_config (google.cloud.retail_v2beta.types.AlertConfig): + Required. The + [AlertConfig][google.cloud.retail.v2beta.AlertConfig] to + update. + + If the caller does not have permission to update the + [AlertConfig][google.cloud.retail.v2beta.AlertConfig], + then a PERMISSION_DENIED error is returned. + + If the + [AlertConfig][google.cloud.retail.v2beta.AlertConfig] to + update does not exist, a NOT_FOUND error is returned. + + This corresponds to the ``alert_config`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + update_mask (google.protobuf.field_mask_pb2.FieldMask): + Indicates which fields in the provided + [AlertConfig][google.cloud.retail.v2beta.AlertConfig] to + update. If not set, all supported fields are updated. + + This corresponds to the ``update_mask`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.cloud.retail_v2beta.types.AlertConfig: + Project level alert config. + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + has_flattened_params = any([alert_config, update_mask]) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, project_service.UpdateAlertConfigRequest): + request = project_service.UpdateAlertConfigRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if alert_config is not None: + request.alert_config = alert_config + if update_mask is not None: + request.update_mask = update_mask + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.update_alert_config] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("alert_config.name", request.alert_config.name),) + ), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + def __enter__(self) -> "ProjectServiceClient": + return self + + def __exit__(self, type, value, traceback): + """Releases underlying transport's resources. + + .. warning:: + ONLY use as a context manager if the transport is NOT shared + with other clients! Exiting the with block will CLOSE the transport + and may cause errors in other clients! + """ + self.transport.close() + + def list_operations( + self, + request: Optional[operations_pb2.ListOperationsRequest] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operations_pb2.ListOperationsResponse: + r"""Lists operations that match the specified filter in the request. + + Args: + request (:class:`~.operations_pb2.ListOperationsRequest`): + The request object. Request message for + `ListOperations` method. + retry (google.api_core.retry.Retry): Designation of what errors, + if any, should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + Returns: + ~.operations_pb2.ListOperationsResponse: + Response message for ``ListOperations`` method. + """ + # Create or coerce a protobuf request object. + # The request isn't a proto-plus wrapped type, + # so it must be constructed via keyword expansion. + if isinstance(request, dict): + request = operations_pb2.ListOperationsRequest(**request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method.wrap_method( + self._transport.list_operations, + default_timeout=None, + client_info=DEFAULT_CLIENT_INFO, + ) + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + def get_operation( + self, + request: Optional[operations_pb2.GetOperationRequest] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operations_pb2.Operation: + r"""Gets the latest state of a long-running operation. + + Args: + request (:class:`~.operations_pb2.GetOperationRequest`): + The request object. Request message for + `GetOperation` method. + retry (google.api_core.retry.Retry): Designation of what errors, + if any, should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + Returns: + ~.operations_pb2.Operation: + An ``Operation`` object. + """ + # Create or coerce a protobuf request object. + # The request isn't a proto-plus wrapped type, + # so it must be constructed via keyword expansion. + if isinstance(request, dict): + request = operations_pb2.GetOperationRequest(**request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method.wrap_method( + self._transport.get_operation, + default_timeout=None, + client_info=DEFAULT_CLIENT_INFO, + ) + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + +DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=package_version.__version__ +) + + +__all__ = ("ProjectServiceClient",) diff --git a/packages/google-cloud-retail/google/cloud/retail_v2beta/services/project_service/transports/__init__.py b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/project_service/transports/__init__.py new file mode 100644 index 000000000000..bfc15c764467 --- /dev/null +++ b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/project_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from collections import OrderedDict +from typing import Dict, Type + +from .base import ProjectServiceTransport +from .grpc import ProjectServiceGrpcTransport +from .grpc_asyncio import ProjectServiceGrpcAsyncIOTransport +from .rest import ProjectServiceRestInterceptor, ProjectServiceRestTransport + +# Compile a registry of transports. +_transport_registry = OrderedDict() # type: Dict[str, Type[ProjectServiceTransport]] +_transport_registry["grpc"] = ProjectServiceGrpcTransport +_transport_registry["grpc_asyncio"] = ProjectServiceGrpcAsyncIOTransport +_transport_registry["rest"] = ProjectServiceRestTransport + +__all__ = ( + "ProjectServiceTransport", + "ProjectServiceGrpcTransport", + "ProjectServiceGrpcAsyncIOTransport", + "ProjectServiceRestTransport", + "ProjectServiceRestInterceptor", +) diff --git a/packages/google-cloud-retail/google/cloud/retail_v2beta/services/project_service/transports/base.py b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/project_service/transports/base.py new file mode 100644 index 000000000000..9e8bff3aceaf --- /dev/null +++ b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/project_service/transports/base.py @@ -0,0 +1,198 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import abc +from typing import Awaitable, Callable, Dict, Optional, Sequence, Union + +import google.api_core +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1 +from google.api_core import retry as retries +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.cloud.location import locations_pb2 # type: ignore +from google.longrunning import operations_pb2 # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.cloud.retail_v2beta import gapic_version as package_version +from google.cloud.retail_v2beta.types import project, project_service + +DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=package_version.__version__ +) + + +class ProjectServiceTransport(abc.ABC): + """Abstract transport class for ProjectService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/cloud-platform",) + + DEFAULT_HOST: str = "retail.googleapis.com" + + def __init__( + self, + *, + host: str = DEFAULT_HOST, + credentials: Optional[ga_credentials.Credentials] = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + quota_project_id: Optional[str] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, + api_audience: Optional[str] = None, + **kwargs, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to (default: 'retail.googleapis.com'). + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A list of scopes. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + """ + + scopes_kwargs = {"scopes": scopes, "default_scopes": self.AUTH_SCOPES} + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, **scopes_kwargs, quota_project_id=quota_project_id + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + **scopes_kwargs, quota_project_id=quota_project_id + ) + # Don't apply audience if the credentials file passed from user. + if hasattr(credentials, "with_gdch_audience"): + credentials = credentials.with_gdch_audience( + api_audience if api_audience else host + ) + + # If the credentials are service account credentials, then always try to use self signed JWT. + if ( + always_use_jwt_access + and isinstance(credentials, service_account.Credentials) + and hasattr(service_account.Credentials, "with_always_use_jwt_access") + ): + credentials = credentials.with_always_use_jwt_access(True) + + # Save the credentials. + self._credentials = credentials + + # Save the hostname. Default to port 443 (HTTPS) if none is specified. + if ":" not in host: + host += ":443" + self._host = host + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.get_alert_config: gapic_v1.method.wrap_method( + self.get_alert_config, + default_timeout=None, + client_info=client_info, + ), + self.update_alert_config: gapic_v1.method.wrap_method( + self.update_alert_config, + default_timeout=None, + client_info=client_info, + ), + } + + def close(self): + """Closes resources associated with the transport. + + .. warning:: + Only call this method if the transport is NOT shared + with other clients - this may cause errors in other clients! + """ + raise NotImplementedError() + + @property + def get_alert_config( + self, + ) -> Callable[ + [project_service.GetAlertConfigRequest], + Union[project.AlertConfig, Awaitable[project.AlertConfig]], + ]: + raise NotImplementedError() + + @property + def update_alert_config( + self, + ) -> Callable[ + [project_service.UpdateAlertConfigRequest], + Union[project.AlertConfig, Awaitable[project.AlertConfig]], + ]: + raise NotImplementedError() + + @property + def list_operations( + self, + ) -> Callable[ + [operations_pb2.ListOperationsRequest], + Union[ + operations_pb2.ListOperationsResponse, + Awaitable[operations_pb2.ListOperationsResponse], + ], + ]: + raise NotImplementedError() + + @property + def get_operation( + self, + ) -> Callable[ + [operations_pb2.GetOperationRequest], + Union[operations_pb2.Operation, Awaitable[operations_pb2.Operation]], + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("ProjectServiceTransport",) diff --git a/packages/google-cloud-retail/google/cloud/retail_v2beta/services/project_service/transports/grpc.py b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/project_service/transports/grpc.py new file mode 100644 index 000000000000..5fb4dfbc60bd --- /dev/null +++ b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/project_service/transports/grpc.py @@ -0,0 +1,336 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from typing import Callable, Dict, Optional, Sequence, Tuple, Union +import warnings + +from google.api_core import gapic_v1, grpc_helpers +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.cloud.location import locations_pb2 # type: ignore +from google.longrunning import operations_pb2 # type: ignore +import grpc # type: ignore + +from google.cloud.retail_v2beta.types import project, project_service + +from .base import DEFAULT_CLIENT_INFO, ProjectServiceTransport + + +class ProjectServiceGrpcTransport(ProjectServiceTransport): + """gRPC backend transport for ProjectService. + + Service for settings at Project level. + + This class defines the same methods as the primary client, so the + primary client can load the underlying transport implementation + and call it. + + It sends protocol buffers over the wire using gRPC (which is built on + top of HTTP/2); the ``grpcio`` package must be installed. + """ + + _stubs: Dict[str, Callable] + + def __init__( + self, + *, + host: str = "retail.googleapis.com", + credentials: Optional[ga_credentials.Credentials] = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + channel: Optional[Union[grpc.Channel, Callable[..., grpc.Channel]]] = None, + api_mtls_endpoint: Optional[str] = None, + client_cert_source: Optional[Callable[[], Tuple[bytes, bytes]]] = None, + ssl_channel_credentials: Optional[grpc.ChannelCredentials] = None, + client_cert_source_for_mtls: Optional[Callable[[], Tuple[bytes, bytes]]] = None, + quota_project_id: Optional[str] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, + api_audience: Optional[str] = None, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to (default: 'retail.googleapis.com'). + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if a ``channel`` instance is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if a ``channel`` instance is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if a ``channel`` instance is provided. + channel (Optional[Union[grpc.Channel, Callable[..., grpc.Channel]]]): + A ``Channel`` instance through which to make calls, or a Callable + that constructs and returns one. If set to None, ``self.create_channel`` + is used to create the channel. If a Callable is given, it will be called + with the same arguments as used in ``self.create_channel``. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if a ``channel`` instance is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if a ``channel`` instance or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn("client_cert_source is deprecated", DeprecationWarning) + + if isinstance(channel, grpc.Channel): + # Ignore credentials if a channel was passed. + credentials = None + self._ignore_credentials = True + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + else: + self._ssl_channel_credentials = SslCredentials().ssl_credentials + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + api_audience=api_audience, + ) + + if not self._grpc_channel: + # initialize with the provided callable or the default channel + channel_init = channel or type(self).create_channel + self._grpc_channel = channel_init( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "retail.googleapis.com", + credentials: Optional[ga_credentials.Credentials] = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + quota_project_id: Optional[str] = None, + **kwargs, + ) -> grpc.Channel: + """Create and return a gRPC channel object. + Args: + host (Optional[str]): The host for the channel to use. + credentials (Optional[~.Credentials]): The + authorization credentials to attach to requests. These + credentials identify this application to the service. If + none are specified, the client will attempt to ascertain + the credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def get_alert_config( + self, + ) -> Callable[[project_service.GetAlertConfigRequest], project.AlertConfig]: + r"""Return a callable for the get alert config method over gRPC. + + Get the [AlertConfig][google.cloud.retail.v2beta.AlertConfig] of + the requested project. + + Returns: + Callable[[~.GetAlertConfigRequest], + ~.AlertConfig]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "get_alert_config" not in self._stubs: + self._stubs["get_alert_config"] = self.grpc_channel.unary_unary( + "/google.cloud.retail.v2beta.ProjectService/GetAlertConfig", + request_serializer=project_service.GetAlertConfigRequest.serialize, + response_deserializer=project.AlertConfig.deserialize, + ) + return self._stubs["get_alert_config"] + + @property + def update_alert_config( + self, + ) -> Callable[[project_service.UpdateAlertConfigRequest], project.AlertConfig]: + r"""Return a callable for the update alert config method over gRPC. + + Update the alert config of the requested project. + + Returns: + Callable[[~.UpdateAlertConfigRequest], + ~.AlertConfig]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "update_alert_config" not in self._stubs: + self._stubs["update_alert_config"] = self.grpc_channel.unary_unary( + "/google.cloud.retail.v2beta.ProjectService/UpdateAlertConfig", + request_serializer=project_service.UpdateAlertConfigRequest.serialize, + response_deserializer=project.AlertConfig.deserialize, + ) + return self._stubs["update_alert_config"] + + def close(self): + self.grpc_channel.close() + + @property + def get_operation( + self, + ) -> Callable[[operations_pb2.GetOperationRequest], operations_pb2.Operation]: + r"""Return a callable for the get_operation method over gRPC.""" + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "get_operation" not in self._stubs: + self._stubs["get_operation"] = self.grpc_channel.unary_unary( + "/google.longrunning.Operations/GetOperation", + request_serializer=operations_pb2.GetOperationRequest.SerializeToString, + response_deserializer=operations_pb2.Operation.FromString, + ) + return self._stubs["get_operation"] + + @property + def list_operations( + self, + ) -> Callable[ + [operations_pb2.ListOperationsRequest], operations_pb2.ListOperationsResponse + ]: + r"""Return a callable for the list_operations method over gRPC.""" + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "list_operations" not in self._stubs: + self._stubs["list_operations"] = self.grpc_channel.unary_unary( + "/google.longrunning.Operations/ListOperations", + request_serializer=operations_pb2.ListOperationsRequest.SerializeToString, + response_deserializer=operations_pb2.ListOperationsResponse.FromString, + ) + return self._stubs["list_operations"] + + @property + def kind(self) -> str: + return "grpc" + + +__all__ = ("ProjectServiceGrpcTransport",) diff --git a/packages/google-cloud-retail/google/cloud/retail_v2beta/services/project_service/transports/grpc_asyncio.py b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/project_service/transports/grpc_asyncio.py new file mode 100644 index 000000000000..9f25be82cb5a --- /dev/null +++ b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/project_service/transports/grpc_asyncio.py @@ -0,0 +1,355 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union +import warnings + +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1, grpc_helpers_async +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.cloud.location import locations_pb2 # type: ignore +from google.longrunning import operations_pb2 # type: ignore +import grpc # type: ignore +from grpc.experimental import aio # type: ignore + +from google.cloud.retail_v2beta.types import project, project_service + +from .base import DEFAULT_CLIENT_INFO, ProjectServiceTransport +from .grpc import ProjectServiceGrpcTransport + + +class ProjectServiceGrpcAsyncIOTransport(ProjectServiceTransport): + """gRPC AsyncIO backend transport for ProjectService. + + Service for settings at Project level. + + This class defines the same methods as the primary client, so the + primary client can load the underlying transport implementation + and call it. + + It sends protocol buffers over the wire using gRPC (which is built on + top of HTTP/2); the ``grpcio`` package must be installed. + """ + + _grpc_channel: aio.Channel + _stubs: Dict[str, Callable] = {} + + @classmethod + def create_channel( + cls, + host: str = "retail.googleapis.com", + credentials: Optional[ga_credentials.Credentials] = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + quota_project_id: Optional[str] = None, + **kwargs, + ) -> aio.Channel: + """Create and return a gRPC AsyncIO channel object. + Args: + host (Optional[str]): The host for the channel to use. + credentials (Optional[~.Credentials]): The + authorization credentials to attach to requests. These + credentials identify this application to the service. If + none are specified, the client will attempt to ascertain + the credentials from the environment. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + aio.Channel: A gRPC AsyncIO channel object. + """ + + return grpc_helpers_async.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + def __init__( + self, + *, + host: str = "retail.googleapis.com", + credentials: Optional[ga_credentials.Credentials] = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + channel: Optional[Union[aio.Channel, Callable[..., aio.Channel]]] = None, + api_mtls_endpoint: Optional[str] = None, + client_cert_source: Optional[Callable[[], Tuple[bytes, bytes]]] = None, + ssl_channel_credentials: Optional[grpc.ChannelCredentials] = None, + client_cert_source_for_mtls: Optional[Callable[[], Tuple[bytes, bytes]]] = None, + quota_project_id: Optional[str] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, + api_audience: Optional[str] = None, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to (default: 'retail.googleapis.com'). + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if a ``channel`` instance is provided. + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if a ``channel`` instance is provided. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + channel (Optional[Union[aio.Channel, Callable[..., aio.Channel]]]): + A ``Channel`` instance through which to make calls, or a Callable + that constructs and returns one. If set to None, ``self.create_channel`` + is used to create the channel. If a Callable is given, it will be called + with the same arguments as used in ``self.create_channel``. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if a ``channel`` instance is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if a ``channel`` instance or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + + Raises: + google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn("client_cert_source is deprecated", DeprecationWarning) + + if isinstance(channel, aio.Channel): + # Ignore credentials if a channel was passed. + credentials = None + self._ignore_credentials = True + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + else: + self._ssl_channel_credentials = SslCredentials().ssl_credentials + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + api_audience=api_audience, + ) + + if not self._grpc_channel: + # initialize with the provided callable or the default channel + channel_init = channel or type(self).create_channel + self._grpc_channel = channel_init( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Wrap messages. This must be done after self._grpc_channel exists + self._prep_wrapped_messages(client_info) + + @property + def grpc_channel(self) -> aio.Channel: + """Create the channel designed to connect to this service. + + This property caches on the instance; repeated calls return + the same channel. + """ + # Return the channel from cache. + return self._grpc_channel + + @property + def get_alert_config( + self, + ) -> Callable[ + [project_service.GetAlertConfigRequest], Awaitable[project.AlertConfig] + ]: + r"""Return a callable for the get alert config method over gRPC. + + Get the [AlertConfig][google.cloud.retail.v2beta.AlertConfig] of + the requested project. + + Returns: + Callable[[~.GetAlertConfigRequest], + Awaitable[~.AlertConfig]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "get_alert_config" not in self._stubs: + self._stubs["get_alert_config"] = self.grpc_channel.unary_unary( + "/google.cloud.retail.v2beta.ProjectService/GetAlertConfig", + request_serializer=project_service.GetAlertConfigRequest.serialize, + response_deserializer=project.AlertConfig.deserialize, + ) + return self._stubs["get_alert_config"] + + @property + def update_alert_config( + self, + ) -> Callable[ + [project_service.UpdateAlertConfigRequest], Awaitable[project.AlertConfig] + ]: + r"""Return a callable for the update alert config method over gRPC. + + Update the alert config of the requested project. + + Returns: + Callable[[~.UpdateAlertConfigRequest], + Awaitable[~.AlertConfig]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "update_alert_config" not in self._stubs: + self._stubs["update_alert_config"] = self.grpc_channel.unary_unary( + "/google.cloud.retail.v2beta.ProjectService/UpdateAlertConfig", + request_serializer=project_service.UpdateAlertConfigRequest.serialize, + response_deserializer=project.AlertConfig.deserialize, + ) + return self._stubs["update_alert_config"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.get_alert_config: gapic_v1.method_async.wrap_method( + self.get_alert_config, + default_timeout=None, + client_info=client_info, + ), + self.update_alert_config: gapic_v1.method_async.wrap_method( + self.update_alert_config, + default_timeout=None, + client_info=client_info, + ), + } + + def close(self): + return self.grpc_channel.close() + + @property + def get_operation( + self, + ) -> Callable[[operations_pb2.GetOperationRequest], operations_pb2.Operation]: + r"""Return a callable for the get_operation method over gRPC.""" + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "get_operation" not in self._stubs: + self._stubs["get_operation"] = self.grpc_channel.unary_unary( + "/google.longrunning.Operations/GetOperation", + request_serializer=operations_pb2.GetOperationRequest.SerializeToString, + response_deserializer=operations_pb2.Operation.FromString, + ) + return self._stubs["get_operation"] + + @property + def list_operations( + self, + ) -> Callable[ + [operations_pb2.ListOperationsRequest], operations_pb2.ListOperationsResponse + ]: + r"""Return a callable for the list_operations method over gRPC.""" + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "list_operations" not in self._stubs: + self._stubs["list_operations"] = self.grpc_channel.unary_unary( + "/google.longrunning.Operations/ListOperations", + request_serializer=operations_pb2.ListOperationsRequest.SerializeToString, + response_deserializer=operations_pb2.ListOperationsResponse.FromString, + ) + return self._stubs["list_operations"] + + +__all__ = ("ProjectServiceGrpcAsyncIOTransport",) diff --git a/packages/google-cloud-retail/google/cloud/retail_v2beta/services/project_service/transports/rest.py b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/project_service/transports/rest.py new file mode 100644 index 000000000000..35cd7abc4100 --- /dev/null +++ b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/project_service/transports/rest.py @@ -0,0 +1,641 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +import dataclasses +import json # type: ignore +import re +from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple, Union +import warnings + +from google.api_core import gapic_v1, path_template, rest_helpers, rest_streaming +from google.api_core import exceptions as core_exceptions +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.auth.transport.requests import AuthorizedSession # type: ignore +from google.cloud.location import locations_pb2 # type: ignore +from google.protobuf import json_format +import grpc # type: ignore +from requests import __version__ as requests_version + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault, None] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object, None] # type: ignore + + +from google.longrunning import operations_pb2 # type: ignore + +from google.cloud.retail_v2beta.types import project, project_service + +from .base import DEFAULT_CLIENT_INFO as BASE_DEFAULT_CLIENT_INFO +from .base import ProjectServiceTransport + +DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=BASE_DEFAULT_CLIENT_INFO.gapic_version, + grpc_version=None, + rest_version=requests_version, +) + + +class ProjectServiceRestInterceptor: + """Interceptor for ProjectService. + + Interceptors are used to manipulate requests, request metadata, and responses + in arbitrary ways. + Example use cases include: + * Logging + * Verifying requests according to service or custom semantics + * Stripping extraneous information from responses + + These use cases and more can be enabled by injecting an + instance of a custom subclass when constructing the ProjectServiceRestTransport. + + .. code-block:: python + class MyCustomProjectServiceInterceptor(ProjectServiceRestInterceptor): + def pre_get_alert_config(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_get_alert_config(self, response): + logging.log(f"Received response: {response}") + return response + + def pre_update_alert_config(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_update_alert_config(self, response): + logging.log(f"Received response: {response}") + return response + + transport = ProjectServiceRestTransport(interceptor=MyCustomProjectServiceInterceptor()) + client = ProjectServiceClient(transport=transport) + + + """ + + def pre_get_alert_config( + self, + request: project_service.GetAlertConfigRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[project_service.GetAlertConfigRequest, Sequence[Tuple[str, str]]]: + """Pre-rpc interceptor for get_alert_config + + Override in a subclass to manipulate the request or metadata + before they are sent to the ProjectService server. + """ + return request, metadata + + def post_get_alert_config( + self, response: project.AlertConfig + ) -> project.AlertConfig: + """Post-rpc interceptor for get_alert_config + + Override in a subclass to manipulate the response + after it is returned by the ProjectService server but before + it is returned to user code. + """ + return response + + def pre_update_alert_config( + self, + request: project_service.UpdateAlertConfigRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[project_service.UpdateAlertConfigRequest, Sequence[Tuple[str, str]]]: + """Pre-rpc interceptor for update_alert_config + + Override in a subclass to manipulate the request or metadata + before they are sent to the ProjectService server. + """ + return request, metadata + + def post_update_alert_config( + self, response: project.AlertConfig + ) -> project.AlertConfig: + """Post-rpc interceptor for update_alert_config + + Override in a subclass to manipulate the response + after it is returned by the ProjectService server but before + it is returned to user code. + """ + return response + + def pre_get_operation( + self, + request: operations_pb2.GetOperationRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[operations_pb2.GetOperationRequest, Sequence[Tuple[str, str]]]: + """Pre-rpc interceptor for get_operation + + Override in a subclass to manipulate the request or metadata + before they are sent to the ProjectService server. + """ + return request, metadata + + def post_get_operation( + self, response: operations_pb2.Operation + ) -> operations_pb2.Operation: + """Post-rpc interceptor for get_operation + + Override in a subclass to manipulate the response + after it is returned by the ProjectService server but before + it is returned to user code. + """ + return response + + def pre_list_operations( + self, + request: operations_pb2.ListOperationsRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[operations_pb2.ListOperationsRequest, Sequence[Tuple[str, str]]]: + """Pre-rpc interceptor for list_operations + + Override in a subclass to manipulate the request or metadata + before they are sent to the ProjectService server. + """ + return request, metadata + + def post_list_operations( + self, response: operations_pb2.ListOperationsResponse + ) -> operations_pb2.ListOperationsResponse: + """Post-rpc interceptor for list_operations + + Override in a subclass to manipulate the response + after it is returned by the ProjectService server but before + it is returned to user code. + """ + return response + + +@dataclasses.dataclass +class ProjectServiceRestStub: + _session: AuthorizedSession + _host: str + _interceptor: ProjectServiceRestInterceptor + + +class ProjectServiceRestTransport(ProjectServiceTransport): + """REST backend transport for ProjectService. + + Service for settings at Project level. + + This class defines the same methods as the primary client, so the + primary client can load the underlying transport implementation + and call it. + + It sends JSON representations of protocol buffers over HTTP/1.1 + + """ + + def __init__( + self, + *, + host: str = "retail.googleapis.com", + credentials: Optional[ga_credentials.Credentials] = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + client_cert_source_for_mtls: Optional[Callable[[], Tuple[bytes, bytes]]] = None, + quota_project_id: Optional[str] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, + url_scheme: str = "https", + interceptor: Optional[ProjectServiceRestInterceptor] = None, + api_audience: Optional[str] = None, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to (default: 'retail.googleapis.com'). + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + + credentials_file (Optional[str]): A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + client_cert_source_for_mtls (Callable[[], Tuple[bytes, bytes]]): Client + certificate to configure mutual TLS HTTP channel. It is ignored + if ``channel`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you are developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + url_scheme: the protocol scheme for the API endpoint. Normally + "https", but for testing or local servers, + "http" can be specified. + """ + # Run the base constructor + # TODO(yon-mg): resolve other ctor params i.e. scopes, quota, etc. + # TODO: When custom host (api_endpoint) is set, `scopes` must *also* be set on the + # credentials object + maybe_url_match = re.match("^(?Phttp(?:s)?://)?(?P.*)$", host) + if maybe_url_match is None: + raise ValueError( + f"Unexpected hostname structure: {host}" + ) # pragma: NO COVER + + url_match_items = maybe_url_match.groupdict() + + host = f"{url_scheme}://{host}" if not url_match_items["scheme"] else host + + super().__init__( + host=host, + credentials=credentials, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + api_audience=api_audience, + ) + self._session = AuthorizedSession( + self._credentials, default_host=self.DEFAULT_HOST + ) + if client_cert_source_for_mtls: + self._session.configure_mtls_channel(client_cert_source_for_mtls) + self._interceptor = interceptor or ProjectServiceRestInterceptor() + self._prep_wrapped_messages(client_info) + + class _GetAlertConfig(ProjectServiceRestStub): + def __hash__(self): + return hash("GetAlertConfig") + + __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} + + @classmethod + def _get_unset_required_fields(cls, message_dict): + return { + k: v + for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items() + if k not in message_dict + } + + def __call__( + self, + request: project_service.GetAlertConfigRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> project.AlertConfig: + r"""Call the get alert config method over HTTP. + + Args: + request (~.project_service.GetAlertConfigRequest): + The request object. Request for + [ProjectService.GetAlertConfig][google.cloud.retail.v2beta.ProjectService.GetAlertConfig] + method. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + ~.project.AlertConfig: + Project level alert config. + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "get", + "uri": "/v2beta/{name=projects/*/alertConfig}", + }, + ] + request, metadata = self._interceptor.pre_get_alert_config( + request, metadata + ) + pb_request = project_service.GetAlertConfigRequest.pb(request) + transcoded_request = path_template.transcode(http_options, pb_request) + + uri = transcoded_request["uri"] + method = transcoded_request["method"] + + # Jsonify the query params + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + use_integers_for_enums=True, + ) + ) + query_params.update(self._get_unset_required_fields(query_params)) + + query_params["$alt"] = "json;enum-encoding=int" + + # Send the request + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(self._session, method)( + "{host}{uri}".format(host=self._host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + # Return the response + resp = project.AlertConfig() + pb_resp = project.AlertConfig.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + resp = self._interceptor.post_get_alert_config(resp) + return resp + + class _UpdateAlertConfig(ProjectServiceRestStub): + def __hash__(self): + return hash("UpdateAlertConfig") + + __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} + + @classmethod + def _get_unset_required_fields(cls, message_dict): + return { + k: v + for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items() + if k not in message_dict + } + + def __call__( + self, + request: project_service.UpdateAlertConfigRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> project.AlertConfig: + r"""Call the update alert config method over HTTP. + + Args: + request (~.project_service.UpdateAlertConfigRequest): + The request object. Request for + [ProjectService.UpdateAlertConfig][google.cloud.retail.v2beta.ProjectService.UpdateAlertConfig] + method. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + ~.project.AlertConfig: + Project level alert config. + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "patch", + "uri": "/v2beta/{alert_config.name=projects/*/alertConfig}", + "body": "alert_config", + }, + ] + request, metadata = self._interceptor.pre_update_alert_config( + request, metadata + ) + pb_request = project_service.UpdateAlertConfigRequest.pb(request) + transcoded_request = path_template.transcode(http_options, pb_request) + + # Jsonify the request body + + body = json_format.MessageToJson( + transcoded_request["body"], use_integers_for_enums=True + ) + uri = transcoded_request["uri"] + method = transcoded_request["method"] + + # Jsonify the query params + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + use_integers_for_enums=True, + ) + ) + query_params.update(self._get_unset_required_fields(query_params)) + + query_params["$alt"] = "json;enum-encoding=int" + + # Send the request + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(self._session, method)( + "{host}{uri}".format(host=self._host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + data=body, + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + # Return the response + resp = project.AlertConfig() + pb_resp = project.AlertConfig.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + resp = self._interceptor.post_update_alert_config(resp) + return resp + + @property + def get_alert_config( + self, + ) -> Callable[[project_service.GetAlertConfigRequest], project.AlertConfig]: + # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here. + # In C++ this would require a dynamic_cast + return self._GetAlertConfig(self._session, self._host, self._interceptor) # type: ignore + + @property + def update_alert_config( + self, + ) -> Callable[[project_service.UpdateAlertConfigRequest], project.AlertConfig]: + # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here. + # In C++ this would require a dynamic_cast + return self._UpdateAlertConfig(self._session, self._host, self._interceptor) # type: ignore + + @property + def get_operation(self): + return self._GetOperation(self._session, self._host, self._interceptor) # type: ignore + + class _GetOperation(ProjectServiceRestStub): + def __call__( + self, + request: operations_pb2.GetOperationRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operations_pb2.Operation: + r"""Call the get operation method over HTTP. + + Args: + request (operations_pb2.GetOperationRequest): + The request object for GetOperation method. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + operations_pb2.Operation: Response from GetOperation method. + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "get", + "uri": "/v2beta/{name=projects/*/locations/*/catalogs/*/branches/*/operations/*}", + }, + { + "method": "get", + "uri": "/v2beta/{name=projects/*/locations/*/catalogs/*/operations/*}", + }, + { + "method": "get", + "uri": "/v2beta/{name=projects/*/locations/*/operations/*}", + }, + { + "method": "get", + "uri": "/v2beta/{name=projects/*/operations/*}", + }, + ] + + request, metadata = self._interceptor.pre_get_operation(request, metadata) + request_kwargs = json_format.MessageToDict(request) + transcoded_request = path_template.transcode(http_options, **request_kwargs) + + uri = transcoded_request["uri"] + method = transcoded_request["method"] + + # Jsonify the query params + query_params = json.loads(json.dumps(transcoded_request["query_params"])) + + # Send the request + headers = dict(metadata) + headers["Content-Type"] = "application/json" + + response = getattr(self._session, method)( + "{host}{uri}".format(host=self._host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params), + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + resp = operations_pb2.Operation() + resp = json_format.Parse(response.content.decode("utf-8"), resp) + resp = self._interceptor.post_get_operation(resp) + return resp + + @property + def list_operations(self): + return self._ListOperations(self._session, self._host, self._interceptor) # type: ignore + + class _ListOperations(ProjectServiceRestStub): + def __call__( + self, + request: operations_pb2.ListOperationsRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operations_pb2.ListOperationsResponse: + r"""Call the list operations method over HTTP. + + Args: + request (operations_pb2.ListOperationsRequest): + The request object for ListOperations method. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + operations_pb2.ListOperationsResponse: Response from ListOperations method. + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "get", + "uri": "/v2beta/{name=projects/*/locations/*/catalogs/*}/operations", + }, + { + "method": "get", + "uri": "/v2beta/{name=projects/*/locations/*}/operations", + }, + { + "method": "get", + "uri": "/v2beta/{name=projects/*}/operations", + }, + ] + + request, metadata = self._interceptor.pre_list_operations(request, metadata) + request_kwargs = json_format.MessageToDict(request) + transcoded_request = path_template.transcode(http_options, **request_kwargs) + + uri = transcoded_request["uri"] + method = transcoded_request["method"] + + # Jsonify the query params + query_params = json.loads(json.dumps(transcoded_request["query_params"])) + + # Send the request + headers = dict(metadata) + headers["Content-Type"] = "application/json" + + response = getattr(self._session, method)( + "{host}{uri}".format(host=self._host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params), + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + resp = operations_pb2.ListOperationsResponse() + resp = json_format.Parse(response.content.decode("utf-8"), resp) + resp = self._interceptor.post_list_operations(resp) + return resp + + @property + def kind(self) -> str: + return "rest" + + def close(self): + self._session.close() + + +__all__ = ("ProjectServiceRestTransport",) diff --git a/packages/google-cloud-retail/google/cloud/retail_v2beta/services/user_event_service/async_client.py b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/user_event_service/async_client.py index eee576ad894a..4c991a2c3be8 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2beta/services/user_event_service/async_client.py +++ b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/user_event_service/async_client.py @@ -52,6 +52,7 @@ from google.cloud.retail_v2beta.types import ( common, + export_config, import_config, purge_config, user_event, @@ -718,6 +719,113 @@ async def sample_import_user_events(): # Done; return the response. return response + async def export_user_events( + self, + request: Optional[Union[export_config.ExportUserEventsRequest, dict]] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operation_async.AsyncOperation: + r"""Exports user events. + + ``Operation.response`` is of type ``ExportResponse``. + ``Operation.metadata`` is of type ``ExportMetadata``. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import retail_v2beta + + async def sample_export_user_events(): + # Create a client + client = retail_v2beta.UserEventServiceAsyncClient() + + # Initialize request argument(s) + output_config = retail_v2beta.OutputConfig() + output_config.gcs_destination.output_uri_prefix = "output_uri_prefix_value" + + request = retail_v2beta.ExportUserEventsRequest( + parent="parent_value", + output_config=output_config, + ) + + # Make the request + operation = client.export_user_events(request=request) + + print("Waiting for operation to complete...") + + response = (await operation).result() + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.retail_v2beta.types.ExportUserEventsRequest, dict]]): + The request object. Request message for the ``ExportUserEvents`` method. + retry (google.api_core.retry_async.AsyncRetry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.api_core.operation_async.AsyncOperation: + An object representing a long-running operation. + + The result type for the operation will be :class:`google.cloud.retail_v2beta.types.ExportUserEventsResponse` Response of the ExportUserEventsRequest. If the long running + operation was successful, then this message is + returned by the + google.longrunning.Operations.response field if the + operation was successful. + + """ + # Create or coerce a protobuf request object. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, export_config.ExportUserEventsRequest): + request = export_config.ExportUserEventsRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.export_user_events + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Wrap the response in an operation future. + response = operation_async.from_gapic( + response, + self._client._transport.operations_client, + export_config.ExportUserEventsResponse, + metadata_type=export_config.ExportMetadata, + ) + + # Done; return the response. + return response + async def rejoin_user_events( self, request: Optional[ diff --git a/packages/google-cloud-retail/google/cloud/retail_v2beta/services/user_event_service/client.py b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/user_event_service/client.py index bdfe04bb7c5b..08bc8d8b97ee 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2beta/services/user_event_service/client.py +++ b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/user_event_service/client.py @@ -58,6 +58,7 @@ from google.cloud.retail_v2beta.types import ( common, + export_config, import_config, purge_config, user_event, @@ -1158,6 +1159,111 @@ def sample_import_user_events(): # Done; return the response. return response + def export_user_events( + self, + request: Optional[Union[export_config.ExportUserEventsRequest, dict]] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operation.Operation: + r"""Exports user events. + + ``Operation.response`` is of type ``ExportResponse``. + ``Operation.metadata`` is of type ``ExportMetadata``. + + .. code-block:: python + + # This snippet has been automatically generated and should be regarded as a + # code template only. + # It will require modifications to work: + # - It may require correct/in-range values for request initialization. + # - It may require specifying regional endpoints when creating the service + # client as shown in: + # https://googleapis.dev/python/google-api-core/latest/client_options.html + from google.cloud import retail_v2beta + + def sample_export_user_events(): + # Create a client + client = retail_v2beta.UserEventServiceClient() + + # Initialize request argument(s) + output_config = retail_v2beta.OutputConfig() + output_config.gcs_destination.output_uri_prefix = "output_uri_prefix_value" + + request = retail_v2beta.ExportUserEventsRequest( + parent="parent_value", + output_config=output_config, + ) + + # Make the request + operation = client.export_user_events(request=request) + + print("Waiting for operation to complete...") + + response = operation.result() + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.retail_v2beta.types.ExportUserEventsRequest, dict]): + The request object. Request message for the ``ExportUserEvents`` method. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + google.api_core.operation.Operation: + An object representing a long-running operation. + + The result type for the operation will be :class:`google.cloud.retail_v2beta.types.ExportUserEventsResponse` Response of the ExportUserEventsRequest. If the long running + operation was successful, then this message is + returned by the + google.longrunning.Operations.response field if the + operation was successful. + + """ + # Create or coerce a protobuf request object. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, export_config.ExportUserEventsRequest): + request = export_config.ExportUserEventsRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.export_user_events] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("parent", request.parent),)), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Wrap the response in an operation future. + response = operation.from_gapic( + response, + self._transport.operations_client, + export_config.ExportUserEventsResponse, + metadata_type=export_config.ExportMetadata, + ) + + # Done; return the response. + return response + def rejoin_user_events( self, request: Optional[ diff --git a/packages/google-cloud-retail/google/cloud/retail_v2beta/services/user_event_service/transports/base.py b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/user_event_service/transports/base.py index 34324ad7a0f6..3ffc64b62fab 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2beta/services/user_event_service/transports/base.py +++ b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/user_event_service/transports/base.py @@ -29,6 +29,7 @@ from google.cloud.retail_v2beta import gapic_version as package_version from google.cloud.retail_v2beta.types import ( + export_config, import_config, purge_config, user_event, @@ -176,6 +177,11 @@ def _prep_wrapped_messages(self, client_info): default_timeout=600.0, client_info=client_info, ), + self.export_user_events: gapic_v1.method.wrap_method( + self.export_user_events, + default_timeout=None, + client_info=client_info, + ), self.rejoin_user_events: gapic_v1.method.wrap_method( self.rejoin_user_events, default_timeout=None, @@ -233,6 +239,15 @@ def import_user_events( ]: raise NotImplementedError() + @property + def export_user_events( + self, + ) -> Callable[ + [export_config.ExportUserEventsRequest], + Union[operations_pb2.Operation, Awaitable[operations_pb2.Operation]], + ]: + raise NotImplementedError() + @property def rejoin_user_events( self, diff --git a/packages/google-cloud-retail/google/cloud/retail_v2beta/services/user_event_service/transports/grpc.py b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/user_event_service/transports/grpc.py index 2de6dee2ff4d..b62f034833fd 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2beta/services/user_event_service/transports/grpc.py +++ b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/user_event_service/transports/grpc.py @@ -26,6 +26,7 @@ import grpc # type: ignore from google.cloud.retail_v2beta.types import ( + export_config, import_config, purge_config, user_event, @@ -378,6 +379,35 @@ def import_user_events( ) return self._stubs["import_user_events"] + @property + def export_user_events( + self, + ) -> Callable[[export_config.ExportUserEventsRequest], operations_pb2.Operation]: + r"""Return a callable for the export user events method over gRPC. + + Exports user events. + + ``Operation.response`` is of type ``ExportResponse``. + ``Operation.metadata`` is of type ``ExportMetadata``. + + Returns: + Callable[[~.ExportUserEventsRequest], + ~.Operation]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "export_user_events" not in self._stubs: + self._stubs["export_user_events"] = self.grpc_channel.unary_unary( + "/google.cloud.retail.v2beta.UserEventService/ExportUserEvents", + request_serializer=export_config.ExportUserEventsRequest.serialize, + response_deserializer=operations_pb2.Operation.FromString, + ) + return self._stubs["export_user_events"] + @property def rejoin_user_events( self, diff --git a/packages/google-cloud-retail/google/cloud/retail_v2beta/services/user_event_service/transports/grpc_asyncio.py b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/user_event_service/transports/grpc_asyncio.py index e950d1420bb7..f32491d3baae 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2beta/services/user_event_service/transports/grpc_asyncio.py +++ b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/user_event_service/transports/grpc_asyncio.py @@ -28,6 +28,7 @@ from grpc.experimental import aio # type: ignore from google.cloud.retail_v2beta.types import ( + export_config, import_config, purge_config, user_event, @@ -392,6 +393,37 @@ def import_user_events( ) return self._stubs["import_user_events"] + @property + def export_user_events( + self, + ) -> Callable[ + [export_config.ExportUserEventsRequest], Awaitable[operations_pb2.Operation] + ]: + r"""Return a callable for the export user events method over gRPC. + + Exports user events. + + ``Operation.response`` is of type ``ExportResponse``. + ``Operation.metadata`` is of type ``ExportMetadata``. + + Returns: + Callable[[~.ExportUserEventsRequest], + Awaitable[~.Operation]]: + A function that, when called, will call the underlying RPC + on the server. + """ + # Generate a "stub function" on-the-fly which will actually make + # the request. + # gRPC handles serialization and deserialization, so we just need + # to pass in the functions for each. + if "export_user_events" not in self._stubs: + self._stubs["export_user_events"] = self.grpc_channel.unary_unary( + "/google.cloud.retail.v2beta.UserEventService/ExportUserEvents", + request_serializer=export_config.ExportUserEventsRequest.serialize, + response_deserializer=operations_pb2.Operation.FromString, + ) + return self._stubs["export_user_events"] + @property def rejoin_user_events( self, @@ -474,6 +506,11 @@ def _prep_wrapped_messages(self, client_info): default_timeout=600.0, client_info=client_info, ), + self.export_user_events: gapic_v1.method_async.wrap_method( + self.export_user_events, + default_timeout=None, + client_info=client_info, + ), self.rejoin_user_events: gapic_v1.method_async.wrap_method( self.rejoin_user_events, default_timeout=None, diff --git a/packages/google-cloud-retail/google/cloud/retail_v2beta/services/user_event_service/transports/rest.py b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/user_event_service/transports/rest.py index 8d59da22e50a..e912baee8a47 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2beta/services/user_event_service/transports/rest.py +++ b/packages/google-cloud-retail/google/cloud/retail_v2beta/services/user_event_service/transports/rest.py @@ -47,6 +47,7 @@ from google.longrunning import operations_pb2 # type: ignore from google.cloud.retail_v2beta.types import ( + export_config, import_config, purge_config, user_event, @@ -86,6 +87,14 @@ def post_collect_user_event(self, response): logging.log(f"Received response: {response}") return response + def pre_export_user_events(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_export_user_events(self, response): + logging.log(f"Received response: {response}") + return response + def pre_import_user_events(self, request, metadata): logging.log(f"Received request: {request}") return request, metadata @@ -147,6 +156,29 @@ def post_collect_user_event( """ return response + def pre_export_user_events( + self, + request: export_config.ExportUserEventsRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[export_config.ExportUserEventsRequest, Sequence[Tuple[str, str]]]: + """Pre-rpc interceptor for export_user_events + + Override in a subclass to manipulate the request or metadata + before they are sent to the UserEventService server. + """ + return request, metadata + + def post_export_user_events( + self, response: operations_pb2.Operation + ) -> operations_pb2.Operation: + """Post-rpc interceptor for export_user_events + + Override in a subclass to manipulate the response + after it is returned by the UserEventService server but before + it is returned to user code. + """ + return response + def pre_import_user_events( self, request: import_config.ImportUserEventsRequest, @@ -583,6 +615,101 @@ def __call__( resp = self._interceptor.post_collect_user_event(resp) return resp + class _ExportUserEvents(UserEventServiceRestStub): + def __hash__(self): + return hash("ExportUserEvents") + + __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} + + @classmethod + def _get_unset_required_fields(cls, message_dict): + return { + k: v + for k, v in cls.__REQUIRED_FIELDS_DEFAULT_VALUES.items() + if k not in message_dict + } + + def __call__( + self, + request: export_config.ExportUserEventsRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operations_pb2.Operation: + r"""Call the export user events method over HTTP. + + Args: + request (~.export_config.ExportUserEventsRequest): + The request object. Request message for the ``ExportUserEvents`` method. + retry (google.api_core.retry.Retry): Designation of what errors, if any, + should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + + Returns: + ~.operations_pb2.Operation: + This resource represents a + long-running operation that is the + result of a network API call. + + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "post", + "uri": "/v2beta/{parent=projects/*/locations/*/catalogs/*}/userEvents:export", + "body": "*", + }, + ] + request, metadata = self._interceptor.pre_export_user_events( + request, metadata + ) + pb_request = export_config.ExportUserEventsRequest.pb(request) + transcoded_request = path_template.transcode(http_options, pb_request) + + # Jsonify the request body + + body = json_format.MessageToJson( + transcoded_request["body"], use_integers_for_enums=True + ) + uri = transcoded_request["uri"] + method = transcoded_request["method"] + + # Jsonify the query params + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + use_integers_for_enums=True, + ) + ) + query_params.update(self._get_unset_required_fields(query_params)) + + query_params["$alt"] = "json;enum-encoding=int" + + # Send the request + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(self._session, method)( + "{host}{uri}".format(host=self._host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + data=body, + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + # Return the response + resp = operations_pb2.Operation() + json_format.Parse(response.content, resp, ignore_unknown_fields=True) + resp = self._interceptor.post_export_user_events(resp) + return resp + class _ImportUserEvents(UserEventServiceRestStub): def __hash__(self): return hash("ImportUserEvents") @@ -978,6 +1105,14 @@ def collect_user_event( # In C++ this would require a dynamic_cast return self._CollectUserEvent(self._session, self._host, self._interceptor) # type: ignore + @property + def export_user_events( + self, + ) -> Callable[[export_config.ExportUserEventsRequest], operations_pb2.Operation]: + # The return type is fine, but mypy isn't sophisticated enough to determine what's going on here. + # In C++ this would require a dynamic_cast + return self._ExportUserEvents(self._session, self._host, self._interceptor) # type: ignore + @property def import_user_events( self, diff --git a/packages/google-cloud-retail/google/cloud/retail_v2beta/types/__init__.py b/packages/google-cloud-retail/google/cloud/retail_v2beta/types/__init__.py index 0ac5d54037d9..27d3b1313457 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2beta/types/__init__.py +++ b/packages/google-cloud-retail/google/cloud/retail_v2beta/types/__init__.py @@ -74,12 +74,27 @@ ExportAnalyticsMetricsResponse, ExportErrorsConfig, ExportMetadata, + ExportProductsRequest, ExportProductsResponse, + ExportUserEventsRequest, ExportUserEventsResponse, GcsOutputResult, OutputConfig, OutputResult, ) +from .generative_question import ( + GenerativeQuestionConfig, + GenerativeQuestionsFeatureConfig, +) +from .generative_question_service import ( + BatchUpdateGenerativeQuestionConfigsRequest, + BatchUpdateGenerativeQuestionConfigsResponse, + GetGenerativeQuestionsFeatureConfigRequest, + ListGenerativeQuestionConfigsRequest, + ListGenerativeQuestionConfigsResponse, + UpdateGenerativeQuestionConfigRequest, + UpdateGenerativeQuestionsFeatureConfigRequest, +) from .import_config import ( BigQuerySource, CompletionDataInputConfig, @@ -138,6 +153,8 @@ SetInventoryResponse, UpdateProductRequest, ) +from .project import AlertConfig +from .project_service import GetAlertConfigRequest, UpdateAlertConfigRequest from .promotion import Promotion from .purge_config import ( PurgeMetadata, @@ -147,7 +164,14 @@ PurgeUserEventsRequest, PurgeUserEventsResponse, ) -from .search_service import ExperimentInfo, SearchRequest, SearchResponse +from .search_service import ( + ExperimentInfo, + ProductAttributeInterval, + ProductAttributeValue, + SearchRequest, + SearchResponse, + Tile, +) from .serving_config import ServingConfig from .serving_config_service import ( AddControlRequest, @@ -222,11 +246,22 @@ "ExportAnalyticsMetricsResponse", "ExportErrorsConfig", "ExportMetadata", + "ExportProductsRequest", "ExportProductsResponse", + "ExportUserEventsRequest", "ExportUserEventsResponse", "GcsOutputResult", "OutputConfig", "OutputResult", + "GenerativeQuestionConfig", + "GenerativeQuestionsFeatureConfig", + "BatchUpdateGenerativeQuestionConfigsRequest", + "BatchUpdateGenerativeQuestionConfigsResponse", + "GetGenerativeQuestionsFeatureConfigRequest", + "ListGenerativeQuestionConfigsRequest", + "ListGenerativeQuestionConfigsResponse", + "UpdateGenerativeQuestionConfigRequest", + "UpdateGenerativeQuestionsFeatureConfigRequest", "BigQuerySource", "CompletionDataInputConfig", "GcsSource", @@ -280,6 +315,9 @@ "SetInventoryRequest", "SetInventoryResponse", "UpdateProductRequest", + "AlertConfig", + "GetAlertConfigRequest", + "UpdateAlertConfigRequest", "Promotion", "PurgeMetadata", "PurgeProductsMetadata", @@ -288,8 +326,11 @@ "PurgeUserEventsRequest", "PurgeUserEventsResponse", "ExperimentInfo", + "ProductAttributeInterval", + "ProductAttributeValue", "SearchRequest", "SearchResponse", + "Tile", "ServingConfig", "AddControlRequest", "CreateServingConfigRequest", diff --git a/packages/google-cloud-retail/google/cloud/retail_v2beta/types/common.py b/packages/google-cloud-retail/google/cloud/retail_v2beta/types/common.py index 52fc452d6d12..e4c68f33045e 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2beta/types/common.py +++ b/packages/google-cloud-retail/google/cloud/retail_v2beta/types/common.py @@ -543,7 +543,7 @@ class ForceReturnFacetAction(proto.Message): facet_position_adjustments (MutableSequence[google.cloud.retail_v2beta.types.Rule.ForceReturnFacetAction.FacetPositionAdjustment]): Each instance corresponds to a force return attribute for the given condition. There can't - be more 3 instances here. + be more 15 instances here. """ class FacetPositionAdjustment(proto.Message): diff --git a/packages/google-cloud-retail/google/cloud/retail_v2beta/types/completion_service.py b/packages/google-cloud-retail/google/cloud/retail_v2beta/types/completion_service.py index 6b721043b018..9c6e13270682 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2beta/types/completion_service.py +++ b/packages/google-cloud-retail/google/cloud/retail_v2beta/types/completion_service.py @@ -108,9 +108,9 @@ class CompleteQueryRequest(proto.Message): higher, it will be capped by 20. enable_attribute_suggestions (bool): If true, attribute suggestions are enabled - and provided in response. - This field is only available for "cloud-retail" - dataset. + and provided in the response. + This field is only available for the + "cloud-retail" dataset. entity (str): The entity for customers who run multiple entities, domains, sites, or regions, for example, ``Google US``, @@ -195,6 +195,15 @@ class CompleteQueryResponse(proto.Message): Recent searches are deduplicated. More recent searches will be reserved when duplication happens. + attribute_results (MutableMapping[str, google.cloud.retail_v2beta.types.CompleteQueryResponse.AttributeResult]): + A map of matched attribute suggestions. This field is only + available for "cloud-retail" dataset. + + Current supported keys: + + - ``brands`` + + - ``categories`` """ class CompletionResult(proto.Message): @@ -239,6 +248,20 @@ class RecentSearchResult(proto.Message): number=1, ) + class AttributeResult(proto.Message): + r"""Resource that represents attribute results. + The list of suggestions for the attribute. + + Attributes: + suggestions (MutableSequence[str]): + + """ + + suggestions: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=1, + ) + completion_results: MutableSequence[CompletionResult] = proto.RepeatedField( proto.MESSAGE, number=1, @@ -253,6 +276,12 @@ class RecentSearchResult(proto.Message): number=3, message=RecentSearchResult, ) + attribute_results: MutableMapping[str, AttributeResult] = proto.MapField( + proto.STRING, + proto.MESSAGE, + number=4, + message=AttributeResult, + ) __all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/packages/google-cloud-retail/google/cloud/retail_v2beta/types/export_config.py b/packages/google-cloud-retail/google/cloud/retail_v2beta/types/export_config.py index c15194a47c71..ef936f6e11e2 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2beta/types/export_config.py +++ b/packages/google-cloud-retail/google/cloud/retail_v2beta/types/export_config.py @@ -26,6 +26,8 @@ manifest={ "OutputConfig", "ExportErrorsConfig", + "ExportProductsRequest", + "ExportUserEventsRequest", "ExportAnalyticsMetricsRequest", "ExportMetadata", "ExportProductsResponse", @@ -147,6 +149,145 @@ class ExportErrorsConfig(proto.Message): ) +class ExportProductsRequest(proto.Message): + r"""Request message for ExportProducts method. + + Attributes: + parent (str): + Required. Resource name of a + [Branch][google.cloud.retail.v2beta.Branch], and + ``default_branch`` for branch_id component is supported. For + example + ``projects/1234/locations/global/catalogs/default_catalog/branches/default_branch`` + output_config (google.cloud.retail_v2beta.types.OutputConfig): + Required. The output location of the data. + filter (str): + A filtering expression to specify restrictions on returned + events. The expression is a sequence of terms. Each term + applies a restriction to the returned products. Use this + expression to restrict results to a specific time range, + tag, or stock state or to filter products by product type. + For example, + ``lastModifiedTime > "2012-04-23T18:25:43.511Z" lastModifiedTime<"2012-04-23T18:25:43.511Z" productType=primary`` + + We expect only four types of fields: + + :: + + * `lastModifiedTime`: This can be specified twice, once with a + less than operator and once with a greater than operator. The + `lastModifiedTime` restriction should result in one, contiguous, + valid, last-modified, time range. + + * `productType`: Supported values are `primary` and `variant`. The + Boolean operators `OR` and `NOT` are supported if the expression is + enclosed in parentheses and must be separated from the + `productType` values by a space. + + * `availability`: Supported values are `IN_STOCK`, `OUT_OF_STOCK`, + `PREORDER`, and `BACKORDER`. Boolean operators `OR` and `NOT` are + supported if the expression is enclosed in parentheses and must be + separated from the `availability` values by a space. + + * `Tag expressions`: Restricts output to products that match all of the + specified tags. Boolean operators `OR` and `NOT` are supported if the + expression is enclosed in parentheses and the operators are separated + from the tag values by a space. Also supported is '`-"tagA"`', which + is equivalent to '`NOT "tagA"`'. Tag values must be double-quoted, + UTF-8 encoded strings and have a size limit of 1,000 characters. + + Some examples of valid filters expressions: + + - Example 1: + ``lastModifiedTime > "2012-04-23T18:25:43.511Z" lastModifiedTime < "2012-04-23T18:30:43.511Z"`` + - Example 2: + ``lastModifiedTime > "2012-04-23T18:25:43.511Z" productType = "variant"`` + - Example 3: + ``tag=("Red" OR "Blue") tag="New-Arrival" tag=(NOT "promotional") productType = "primary" lastModifiedTime < "2018-04-23T18:30:43.511Z"`` + - Example 4: + ``lastModifiedTime > "2012-04-23T18:25:43.511Z"`` + - Example 5: ``availability = (IN_STOCK OR BACKORDER)`` + """ + + parent: str = proto.Field( + proto.STRING, + number=1, + ) + output_config: "OutputConfig" = proto.Field( + proto.MESSAGE, + number=2, + message="OutputConfig", + ) + filter: str = proto.Field( + proto.STRING, + number=3, + ) + + +class ExportUserEventsRequest(proto.Message): + r"""Request message for the ``ExportUserEvents`` method. + + Attributes: + parent (str): + Required. Resource name of a + [Catalog][google.cloud.retail.v2beta.Catalog]. For example + ``projects/1234/locations/global/catalogs/default_catalog`` + output_config (google.cloud.retail_v2beta.types.OutputConfig): + Required. The output location of the data. + filter (str): + A filtering expression to specify restrictions on returned + events. The expression is a sequence of terms. Each term + applies a restriction to the returned user events. Use this + expression to restrict results to a specific time range or + to filter events by eventType. For example, + ``eventTime > "2012-04-23T18:25:43.511Z" eventsMissingCatalogItems eventTime<"2012-04-23T18:25:43.511Z" eventType=search`` + + We expect only three types of fields: + + :: + + * `eventTime`: This can be specified twice, once with a + less than operator and once with a greater than operator. The + `eventTime` restriction should result in one, contiguous, valid, + `eventTime` range. + + * `eventType`: Boolean operators `OR` and `NOT` are supported if the + expression is enclosed in parentheses and the operators are separated + from the tag values by a space. + + * `eventsMissingCatalogItems`: This restricts results + to events for which catalog items were not found in the catalog. The + default behavior is to return only those events for which catalog + items were found. + + Some examples of valid filters expressions: + + - Example 1: + ``eventTime > "2012-04-23T18:25:43.511Z" eventTime < "2012-04-23T18:30:43.511Z"`` + - Example 2: + ``eventTime > "2012-04-23T18:25:43.511Z" eventType = detail-page-view`` + - Example 3: + ``eventsMissingCatalogItems eventType = (NOT search) eventTime < "2018-04-23T18:30:43.511Z"`` + - Example 4: ``eventTime > "2012-04-23T18:25:43.511Z"`` + - Example 5: ``eventType = (detail-page-view OR search)`` + - Example 6: ``eventsMissingCatalogItems`` + """ + + parent: str = proto.Field( + proto.STRING, + number=1, + ) + output_config: "OutputConfig" = proto.Field( + proto.MESSAGE, + number=2, + message="OutputConfig", + ) + filter: str = proto.Field( + proto.STRING, + number=3, + ) + + class ExportAnalyticsMetricsRequest(proto.Message): r"""Request message for the ``ExportAnalyticsMetrics`` method. diff --git a/packages/google-cloud-retail/google/cloud/retail_v2beta/types/generative_question.py b/packages/google-cloud-retail/google/cloud/retail_v2beta/types/generative_question.py new file mode 100644 index 000000000000..e88ed702c819 --- /dev/null +++ b/packages/google-cloud-retail/google/cloud/retail_v2beta/types/generative_question.py @@ -0,0 +1,122 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + +from typing import MutableMapping, MutableSequence + +import proto # type: ignore + +__protobuf__ = proto.module( + package="google.cloud.retail.v2beta", + manifest={ + "GenerativeQuestionsFeatureConfig", + "GenerativeQuestionConfig", + }, +) + + +class GenerativeQuestionsFeatureConfig(proto.Message): + r"""Configuration for overall generative question feature state. + + Attributes: + catalog (str): + Required. Resource name of the affected + catalog. Format: + projects/{project}/locations/{location}/catalogs/{catalog} + feature_enabled (bool): + Optional. Determines whether questions will + be used at serving time. Note: This feature + cannot be enabled until initial data + requirements are satisfied. + minimum_products (int): + Optional. Minimum number of products in the + response to trigger follow-up questions. Value + must be 0 or positive. + """ + + catalog: str = proto.Field( + proto.STRING, + number=1, + ) + feature_enabled: bool = proto.Field( + proto.BOOL, + number=2, + ) + minimum_products: int = proto.Field( + proto.INT32, + number=3, + ) + + +class GenerativeQuestionConfig(proto.Message): + r"""Configuration for a single generated question. + + Attributes: + catalog (str): + Required. Resource name of the catalog. + Format: + projects/{project}/locations/{location}/catalogs/{catalog} + facet (str): + Required. The facet to which the question is + associated. + generated_question (str): + Output only. The LLM generated question. + final_question (str): + Optional. The question that will be used at serving time. + Question can have a max length of 300 bytes. When not + populated, generated_question should be used. + example_values (MutableSequence[str]): + Output only. Values that can be used to + answer the question. + frequency (float): + Output only. The ratio of how often a + question was asked. + allowed_in_conversation (bool): + Optional. Whether the question is asked at + serving time. + """ + + catalog: str = proto.Field( + proto.STRING, + number=1, + ) + facet: str = proto.Field( + proto.STRING, + number=2, + ) + generated_question: str = proto.Field( + proto.STRING, + number=3, + ) + final_question: str = proto.Field( + proto.STRING, + number=4, + ) + example_values: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=5, + ) + frequency: float = proto.Field( + proto.FLOAT, + number=6, + ) + allowed_in_conversation: bool = proto.Field( + proto.BOOL, + number=7, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/packages/google-cloud-retail/google/cloud/retail_v2beta/types/generative_question_service.py b/packages/google-cloud-retail/google/cloud/retail_v2beta/types/generative_question_service.py new file mode 100644 index 000000000000..24ac853fa1d1 --- /dev/null +++ b/packages/google-cloud-retail/google/cloud/retail_v2beta/types/generative_question_service.py @@ -0,0 +1,187 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + +from typing import MutableMapping, MutableSequence + +from google.protobuf import field_mask_pb2 # type: ignore +import proto # type: ignore + +from google.cloud.retail_v2beta.types import generative_question + +__protobuf__ = proto.module( + package="google.cloud.retail.v2beta", + manifest={ + "UpdateGenerativeQuestionsFeatureConfigRequest", + "GetGenerativeQuestionsFeatureConfigRequest", + "ListGenerativeQuestionConfigsRequest", + "ListGenerativeQuestionConfigsResponse", + "UpdateGenerativeQuestionConfigRequest", + "BatchUpdateGenerativeQuestionConfigsRequest", + "BatchUpdateGenerativeQuestionConfigsResponse", + }, +) + + +class UpdateGenerativeQuestionsFeatureConfigRequest(proto.Message): + r"""Request for UpdateGenerativeQuestionsFeatureConfig method. + + Attributes: + generative_questions_feature_config (google.cloud.retail_v2beta.types.GenerativeQuestionsFeatureConfig): + Required. The configuration managing the + feature state. + update_mask (google.protobuf.field_mask_pb2.FieldMask): + Optional. Indicates which fields in the provided + [GenerativeQuestionsFeatureConfig][google.cloud.retail.v2beta.GenerativeQuestionsFeatureConfig] + to update. If not set or empty, all supported fields are + updated. + """ + + generative_questions_feature_config: generative_question.GenerativeQuestionsFeatureConfig = proto.Field( + proto.MESSAGE, + number=2, + message=generative_question.GenerativeQuestionsFeatureConfig, + ) + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=4, + message=field_mask_pb2.FieldMask, + ) + + +class GetGenerativeQuestionsFeatureConfigRequest(proto.Message): + r"""Request for GetGenerativeQuestionsFeatureConfig method. + + Attributes: + catalog (str): + Required. Resource name of the parent + catalog. Format: + projects/{project}/locations/{location}/catalogs/{catalog} + """ + + catalog: str = proto.Field( + proto.STRING, + number=1, + ) + + +class ListGenerativeQuestionConfigsRequest(proto.Message): + r"""Request for ListQuestions method. + + Attributes: + parent (str): + Required. Resource name of the parent + catalog. Format: + projects/{project}/locations/{location}/catalogs/{catalog} + """ + + parent: str = proto.Field( + proto.STRING, + number=1, + ) + + +class ListGenerativeQuestionConfigsResponse(proto.Message): + r"""Response for ListQuestions method. + + Attributes: + generative_question_configs (MutableSequence[google.cloud.retail_v2beta.types.GenerativeQuestionConfig]): + All the questions for a given catalog. + """ + + generative_question_configs: MutableSequence[ + generative_question.GenerativeQuestionConfig + ] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message=generative_question.GenerativeQuestionConfig, + ) + + +class UpdateGenerativeQuestionConfigRequest(proto.Message): + r"""Request for UpdateGenerativeQuestionConfig method. + + Attributes: + generative_question_config (google.cloud.retail_v2beta.types.GenerativeQuestionConfig): + Required. The question to update. + update_mask (google.protobuf.field_mask_pb2.FieldMask): + Optional. Indicates which fields in the provided + [GenerativeQuestionConfig][google.cloud.retail.v2beta.GenerativeQuestionConfig] + to update. The following are NOT supported: + + - [GenerativeQuestionConfig.frequency][google.cloud.retail.v2beta.GenerativeQuestionConfig.frequency] + + If not set or empty, all supported fields are updated. + """ + + generative_question_config: generative_question.GenerativeQuestionConfig = ( + proto.Field( + proto.MESSAGE, + number=3, + message=generative_question.GenerativeQuestionConfig, + ) + ) + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=4, + message=field_mask_pb2.FieldMask, + ) + + +class BatchUpdateGenerativeQuestionConfigsRequest(proto.Message): + r"""Request for BatchUpdateGenerativeQuestionConfig method. + + Attributes: + parent (str): + Optional. Resource name of the parent + catalog. Format: + projects/{project}/locations/{location}/catalogs/{catalog} + requests (MutableSequence[google.cloud.retail_v2beta.types.UpdateGenerativeQuestionConfigRequest]): + Required. The updates question configs. + """ + + parent: str = proto.Field( + proto.STRING, + number=1, + ) + requests: MutableSequence[ + "UpdateGenerativeQuestionConfigRequest" + ] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="UpdateGenerativeQuestionConfigRequest", + ) + + +class BatchUpdateGenerativeQuestionConfigsResponse(proto.Message): + r"""Aggregated response for UpdateGenerativeQuestionConfig + method. + + Attributes: + generative_question_configs (MutableSequence[google.cloud.retail_v2beta.types.GenerativeQuestionConfig]): + Optional. The updates question configs. + """ + + generative_question_configs: MutableSequence[ + generative_question.GenerativeQuestionConfig + ] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message=generative_question.GenerativeQuestionConfig, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/packages/google-cloud-retail/google/cloud/retail_v2beta/types/product.py b/packages/google-cloud-retail/google/cloud/retail_v2beta/types/product.py index 93555c3686ab..06477dc69bd2 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2beta/types/product.py +++ b/packages/google-cloud-retail/google/cloud/retail_v2beta/types/product.py @@ -346,6 +346,16 @@ class Product(proto.Message): [Product][google.cloud.retail.v2beta.Product]. Default to [Availability.IN_STOCK][google.cloud.retail.v2beta.Product.Availability.IN_STOCK]. + For primary products with variants set the availability of + the primary as + [Availability.OUT_OF_STOCK][google.cloud.retail.v2beta.Product.Availability.OUT_OF_STOCK] + and set the true availability at the variant level. This way + the primary product will be considered "in stock" as long as + it has at least one variant in stock. + + For primary products with no variants set the true + availability at the primary level. + Corresponding properties: Google Merchant Center property `availability `__. Schema.org property @@ -535,9 +545,6 @@ class Product(proto.Message): - [name][google.cloud.retail.v2beta.Product.name] - [color_info][google.cloud.retail.v2beta.Product.color_info] - The maximum number of paths is 30. Otherwise, an - INVALID_ARGUMENT error is returned. - Note: Returning more fields in [SearchResponse][google.cloud.retail.v2beta.SearchResponse] can increase response payload size and serving latency. diff --git a/packages/google-cloud-retail/google/cloud/retail_v2beta/types/project.py b/packages/google-cloud-retail/google/cloud/retail_v2beta/types/project.py new file mode 100644 index 000000000000..ce94cd47361a --- /dev/null +++ b/packages/google-cloud-retail/google/cloud/retail_v2beta/types/project.py @@ -0,0 +1,117 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + +from typing import MutableMapping, MutableSequence + +import proto # type: ignore + +__protobuf__ = proto.module( + package="google.cloud.retail.v2beta", + manifest={ + "AlertConfig", + }, +) + + +class AlertConfig(proto.Message): + r"""Project level alert config. + + Attributes: + name (str): + Required. Immutable. The name of the AlertConfig singleton + resource. Format: `projects/*/alertConfig` + alert_policies (MutableSequence[google.cloud.retail_v2beta.types.AlertConfig.AlertPolicy]): + Alert policies for a customer. They must be unique by + [AlertPolicy.alert_group] + """ + + class AlertPolicy(proto.Message): + r"""Alert policy for a customer. + + Attributes: + alert_group (str): + The feature that provides alerting capability. Supported + value: + + - ``search-data-quality`` for retail search customers. + - ``conv-data-quality`` for retail conversation customers. + enroll_status (google.cloud.retail_v2beta.types.AlertConfig.AlertPolicy.EnrollStatus): + The enrollment status of a customer. + recipients (MutableSequence[google.cloud.retail_v2beta.types.AlertConfig.AlertPolicy.Recipient]): + Recipients for the alert policy. + One alert policy should not exceed 20 + recipients. + """ + + class EnrollStatus(proto.Enum): + r"""The enrollment status enum for alert policy. + + Values: + ENROLL_STATUS_UNSPECIFIED (0): + Default value. Used for customers who have + not responded to the alert policy. + ENROLLED (1): + Customer is enrolled in this policy. + DECLINED (2): + Customer declined this policy. + """ + ENROLL_STATUS_UNSPECIFIED = 0 + ENROLLED = 1 + DECLINED = 2 + + class Recipient(proto.Message): + r"""Recipient contact information. + + Attributes: + email_address (str): + Email address of the recipient. + """ + + email_address: str = proto.Field( + proto.STRING, + number=1, + ) + + alert_group: str = proto.Field( + proto.STRING, + number=1, + ) + enroll_status: "AlertConfig.AlertPolicy.EnrollStatus" = proto.Field( + proto.ENUM, + number=2, + enum="AlertConfig.AlertPolicy.EnrollStatus", + ) + recipients: MutableSequence[ + "AlertConfig.AlertPolicy.Recipient" + ] = proto.RepeatedField( + proto.MESSAGE, + number=3, + message="AlertConfig.AlertPolicy.Recipient", + ) + + name: str = proto.Field( + proto.STRING, + number=1, + ) + alert_policies: MutableSequence[AlertPolicy] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message=AlertPolicy, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/packages/google-cloud-retail/google/cloud/retail_v2beta/types/project_service.py b/packages/google-cloud-retail/google/cloud/retail_v2beta/types/project_service.py new file mode 100644 index 000000000000..7939e8d006af --- /dev/null +++ b/packages/google-cloud-retail/google/cloud/retail_v2beta/types/project_service.py @@ -0,0 +1,86 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +from __future__ import annotations + +from typing import MutableMapping, MutableSequence + +from google.protobuf import field_mask_pb2 # type: ignore +import proto # type: ignore + +from google.cloud.retail_v2beta.types import project + +__protobuf__ = proto.module( + package="google.cloud.retail.v2beta", + manifest={ + "GetAlertConfigRequest", + "UpdateAlertConfigRequest", + }, +) + + +class GetAlertConfigRequest(proto.Message): + r"""Request for + [ProjectService.GetAlertConfig][google.cloud.retail.v2beta.ProjectService.GetAlertConfig] + method. + + Attributes: + name (str): + Required. Full AlertConfig resource name. Format: + projects/{project_number}/alertConfig + """ + + name: str = proto.Field( + proto.STRING, + number=1, + ) + + +class UpdateAlertConfigRequest(proto.Message): + r"""Request for + [ProjectService.UpdateAlertConfig][google.cloud.retail.v2beta.ProjectService.UpdateAlertConfig] + method. + + Attributes: + alert_config (google.cloud.retail_v2beta.types.AlertConfig): + Required. The + [AlertConfig][google.cloud.retail.v2beta.AlertConfig] to + update. + + If the caller does not have permission to update the + [AlertConfig][google.cloud.retail.v2beta.AlertConfig], then + a PERMISSION_DENIED error is returned. + + If the [AlertConfig][google.cloud.retail.v2beta.AlertConfig] + to update does not exist, a NOT_FOUND error is returned. + update_mask (google.protobuf.field_mask_pb2.FieldMask): + Indicates which fields in the provided + [AlertConfig][google.cloud.retail.v2beta.AlertConfig] to + update. If not set, all supported fields are updated. + """ + + alert_config: project.AlertConfig = proto.Field( + proto.MESSAGE, + number=1, + message=project.AlertConfig, + ) + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=2, + message=field_mask_pb2.FieldMask, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/packages/google-cloud-retail/google/cloud/retail_v2beta/types/search_service.py b/packages/google-cloud-retail/google/cloud/retail_v2beta/types/search_service.py index ddc8d1ce8851..fbafe515c73c 100644 --- a/packages/google-cloud-retail/google/cloud/retail_v2beta/types/search_service.py +++ b/packages/google-cloud-retail/google/cloud/retail_v2beta/types/search_service.py @@ -27,6 +27,9 @@ __protobuf__ = proto.module( package="google.cloud.retail.v2beta", manifest={ + "ProductAttributeValue", + "ProductAttributeInterval", + "Tile", "SearchRequest", "SearchResponse", "ExperimentInfo", @@ -34,6 +37,93 @@ ) +class ProductAttributeValue(proto.Message): + r"""Product attribute which structured by an attribute name and value. + This structure is used in conversational search filters and answers. + For example, if we have ``name=color`` and ``value=red``, this means + that the color is ``red``. + + Attributes: + name (str): + The attribute name. + value (str): + The attribute value. + """ + + name: str = proto.Field( + proto.STRING, + number=1, + ) + value: str = proto.Field( + proto.STRING, + number=2, + ) + + +class ProductAttributeInterval(proto.Message): + r"""Product attribute name and numeric interval. + + Attributes: + name (str): + The attribute name (e.g. "length") + interval (google.cloud.retail_v2beta.types.Interval): + The numeric interval (e.g. [10, 20)) + """ + + name: str = proto.Field( + proto.STRING, + number=1, + ) + interval: common.Interval = proto.Field( + proto.MESSAGE, + number=2, + message=common.Interval, + ) + + +class Tile(proto.Message): + r"""This field specifies the tile information including an + attribute key, attribute value. More fields will be added in the + future, eg: product id or product counts, etc. + + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + product_attribute_value (google.cloud.retail_v2beta.types.ProductAttributeValue): + The product attribute key-value. + + This field is a member of `oneof`_ ``product_attribute``. + product_attribute_interval (google.cloud.retail_v2beta.types.ProductAttributeInterval): + The product attribute key-numeric interval. + + This field is a member of `oneof`_ ``product_attribute``. + representative_product_id (str): + The representative product id for this tile. + """ + + product_attribute_value: "ProductAttributeValue" = proto.Field( + proto.MESSAGE, + number=1, + oneof="product_attribute", + message="ProductAttributeValue", + ) + product_attribute_interval: "ProductAttributeInterval" = proto.Field( + proto.MESSAGE, + number=2, + oneof="product_attribute", + message="ProductAttributeInterval", + ) + representative_product_id: str = proto.Field( + proto.STRING, + number=3, + ) + + class SearchRequest(proto.Message): r"""Request message for [SearchService.Search][google.cloud.retail.v2beta.SearchService.Search] @@ -325,6 +415,13 @@ class SearchRequest(proto.Message): matched with [UserEvent.entity][google.cloud.retail.v2beta.UserEvent.entity] to get search results boosted by entity. + conversational_search_spec (google.cloud.retail_v2beta.types.SearchRequest.ConversationalSearchSpec): + Optional. This field specifies all + conversational related parameters addition to + traditional retail search. + tile_navigation_spec (google.cloud.retail_v2beta.types.SearchRequest.TileNavigationSpec): + Optional. This field specifies tile + navigation related parameters. """ class SearchMode(proto.Enum): @@ -907,6 +1004,135 @@ class Mode(proto.Enum): enum="SearchRequest.SpellCorrectionSpec.Mode", ) + class ConversationalSearchSpec(proto.Message): + r"""This field specifies all conversational related parameters + addition to traditional retail search. + + Attributes: + followup_conversation_requested (bool): + This field specifies whether the customer + would like to do conversational search. If this + field is set to true, conversational related + extra information will be returned from server + side, including follow-up question, answer + options, etc. + conversation_id (str): + This field specifies the conversation id, which maintains + the state of the conversation between client side and server + side. Use the value from the previous + [ConversationalSearchResult.conversation_id][]. For the + initial request, this should be empty. + user_answer (google.cloud.retail_v2beta.types.SearchRequest.ConversationalSearchSpec.UserAnswer): + This field specifies the current user answer + during the conversational search. This can be + either user selected from suggested answers or + user input plain text. + """ + + class UserAnswer(proto.Message): + r"""This field specifies the current user answer during the + conversational search. This can be either user selected from + suggested answers or user input plain text. + + This message has `oneof`_ fields (mutually exclusive fields). + For each oneof, at most one member field can be set at the same time. + Setting any member of the oneof automatically clears all other + members. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + text_answer (str): + This field specifies the incremental input + text from the user during the conversational + search. + + This field is a member of `oneof`_ ``type``. + selected_answer (google.cloud.retail_v2beta.types.SearchRequest.ConversationalSearchSpec.UserAnswer.SelectedAnswer): + This field specifies the selected attributes during the + conversational search. This should be a subset of + [ConversationalSearchResult.suggested_answers][]. + + This field is a member of `oneof`_ ``type``. + """ + + class SelectedAnswer(proto.Message): + r"""This field specifies the selected answers during the + conversational search. + + Attributes: + product_attribute_values (MutableSequence[google.cloud.retail_v2beta.types.ProductAttributeValue]): + This field is deprecated and should not be + set. + product_attribute_value (google.cloud.retail_v2beta.types.ProductAttributeValue): + This field specifies the selected answer + which is a attribute key-value. + """ + + product_attribute_values: MutableSequence[ + "ProductAttributeValue" + ] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="ProductAttributeValue", + ) + product_attribute_value: "ProductAttributeValue" = proto.Field( + proto.MESSAGE, + number=2, + message="ProductAttributeValue", + ) + + text_answer: str = proto.Field( + proto.STRING, + number=1, + oneof="type", + ) + selected_answer: "SearchRequest.ConversationalSearchSpec.UserAnswer.SelectedAnswer" = proto.Field( + proto.MESSAGE, + number=2, + oneof="type", + message="SearchRequest.ConversationalSearchSpec.UserAnswer.SelectedAnswer", + ) + + followup_conversation_requested: bool = proto.Field( + proto.BOOL, + number=1, + ) + conversation_id: str = proto.Field( + proto.STRING, + number=2, + ) + user_answer: "SearchRequest.ConversationalSearchSpec.UserAnswer" = proto.Field( + proto.MESSAGE, + number=3, + message="SearchRequest.ConversationalSearchSpec.UserAnswer", + ) + + class TileNavigationSpec(proto.Message): + r"""This field specifies tile navigation related parameters. + + Attributes: + tile_navigation_requested (bool): + This field specifies whether the customer + would like to request tile navigation. + applied_tiles (MutableSequence[google.cloud.retail_v2beta.types.Tile]): + This field specifies the tiles which are already clicked in + client side. NOTE: This field is not being used for + filtering search products. Client side should also put all + the applied tiles in + [SearchRequest.filter][google.cloud.retail.v2beta.SearchRequest.filter]. + """ + + tile_navigation_requested: bool = proto.Field( + proto.BOOL, + number=1, + ) + applied_tiles: MutableSequence["Tile"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="Tile", + ) + placement: str = proto.Field( proto.STRING, number=1, @@ -1005,6 +1231,16 @@ class Mode(proto.Enum): proto.STRING, number=38, ) + conversational_search_spec: ConversationalSearchSpec = proto.Field( + proto.MESSAGE, + number=40, + message=ConversationalSearchSpec, + ) + tile_navigation_spec: TileNavigationSpec = proto.Field( + proto.MESSAGE, + number=41, + message=TileNavigationSpec, + ) class SearchResponse(proto.Message): @@ -1061,6 +1297,14 @@ class SearchResponse(proto.Message): Metadata related to A/B testing [Experiment][] associated with this response. Only exists when an experiment is triggered. + conversational_search_result (google.cloud.retail_v2beta.types.SearchResponse.ConversationalSearchResult): + This field specifies all related information + that is needed on client side for UI rendering + of conversational retail search. + tile_navigation_result (google.cloud.retail_v2beta.types.SearchResponse.TileNavigationResult): + This field specifies all related information + for tile navigation that will be used in client + side. """ class SearchResult(proto.Message): @@ -1309,6 +1553,126 @@ class QueryExpansionInfo(proto.Message): number=2, ) + class ConversationalSearchResult(proto.Message): + r"""This field specifies all related information that is needed + on client side for UI rendering of conversational retail search. + + Attributes: + conversation_id (str): + Conversation UUID. This field will be stored in client side + storage to maintain the conversation session with server and + will be used for next search request's + [SearchRequest.ConversationalSearchSpec.conversation_id][google.cloud.retail.v2beta.SearchRequest.ConversationalSearchSpec.conversation_id] + to restore conversation state in server. + refined_query (str): + The current refined query for the conversational search. + This field will be used in customer UI that the query in the + search bar should be replaced with the refined query. For + example, if + [SearchRequest.query][google.cloud.retail.v2beta.SearchRequest.query] + is ``dress`` and next + [SearchRequest.ConversationalSearchSpec.UserAnswer.text_answer][google.cloud.retail.v2beta.SearchRequest.ConversationalSearchSpec.UserAnswer.text_answer] + is ``red color``, which does not match any product attribute + value filters, the refined query will be + ``dress, red color``. + additional_filters (MutableSequence[google.cloud.retail_v2beta.types.SearchResponse.ConversationalSearchResult.AdditionalFilter]): + This field is deprecated but will be kept for backward + compatibility. There is expected to have only one additional + filter and the value will be the same to the same as field + ``additional_filter``. + followup_question (str): + The follow-up question. e.g., ``What is the color?`` + suggested_answers (MutableSequence[google.cloud.retail_v2beta.types.SearchResponse.ConversationalSearchResult.SuggestedAnswer]): + The answer options provided to client for the + follow-up question. + additional_filter (google.cloud.retail_v2beta.types.SearchResponse.ConversationalSearchResult.AdditionalFilter): + This is the incremental additional filters implied from the + current user answer. User should add the suggested addition + filters to the previous + [SearchRequest.filter][google.cloud.retail.v2beta.SearchRequest.filter], + and use the merged filter in the follow up search request. + """ + + class SuggestedAnswer(proto.Message): + r"""Suggested answers to the follow-up question. + + Attributes: + product_attribute_value (google.cloud.retail_v2beta.types.ProductAttributeValue): + Product attribute value, including an + attribute key and an attribute value. Other + types can be added here in the future. + """ + + product_attribute_value: "ProductAttributeValue" = proto.Field( + proto.MESSAGE, + number=1, + message="ProductAttributeValue", + ) + + class AdditionalFilter(proto.Message): + r"""Additional filter that client side need to apply. + + Attributes: + product_attribute_value (google.cloud.retail_v2beta.types.ProductAttributeValue): + Product attribute value, including an + attribute key and an attribute value. Other + types can be added here in the future. + """ + + product_attribute_value: "ProductAttributeValue" = proto.Field( + proto.MESSAGE, + number=1, + message="ProductAttributeValue", + ) + + conversation_id: str = proto.Field( + proto.STRING, + number=1, + ) + refined_query: str = proto.Field( + proto.STRING, + number=2, + ) + additional_filters: MutableSequence[ + "SearchResponse.ConversationalSearchResult.AdditionalFilter" + ] = proto.RepeatedField( + proto.MESSAGE, + number=3, + message="SearchResponse.ConversationalSearchResult.AdditionalFilter", + ) + followup_question: str = proto.Field( + proto.STRING, + number=4, + ) + suggested_answers: MutableSequence[ + "SearchResponse.ConversationalSearchResult.SuggestedAnswer" + ] = proto.RepeatedField( + proto.MESSAGE, + number=5, + message="SearchResponse.ConversationalSearchResult.SuggestedAnswer", + ) + additional_filter: "SearchResponse.ConversationalSearchResult.AdditionalFilter" = proto.Field( + proto.MESSAGE, + number=6, + message="SearchResponse.ConversationalSearchResult.AdditionalFilter", + ) + + class TileNavigationResult(proto.Message): + r"""This field specifies all related information for tile + navigation that will be used in client side. + + Attributes: + tiles (MutableSequence[google.cloud.retail_v2beta.types.Tile]): + The current tiles that are used for tile + navigation, sorted by engagement. + """ + + tiles: MutableSequence["Tile"] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="Tile", + ) + @property def raw_page(self): return self @@ -1364,6 +1728,16 @@ def raw_page(self): number=17, message="ExperimentInfo", ) + conversational_search_result: ConversationalSearchResult = proto.Field( + proto.MESSAGE, + number=18, + message=ConversationalSearchResult, + ) + tile_navigation_result: TileNavigationResult = proto.Field( + proto.MESSAGE, + number=19, + message=TileNavigationResult, + ) class ExperimentInfo(proto.Message): diff --git a/packages/google-cloud-retail/samples/generated_samples/retail_v2_generated_generative_question_service_batch_update_generative_question_configs_async.py b/packages/google-cloud-retail/samples/generated_samples/retail_v2_generated_generative_question_service_batch_update_generative_question_configs_async.py new file mode 100644 index 000000000000..c25d9a6d9f8e --- /dev/null +++ b/packages/google-cloud-retail/samples/generated_samples/retail_v2_generated_generative_question_service_batch_update_generative_question_configs_async.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for BatchUpdateGenerativeQuestionConfigs +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-retail + + +# [START retail_v2_generated_GenerativeQuestionService_BatchUpdateGenerativeQuestionConfigs_async] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import retail_v2 + + +async def sample_batch_update_generative_question_configs(): + # Create a client + client = retail_v2.GenerativeQuestionServiceAsyncClient() + + # Initialize request argument(s) + requests = retail_v2.UpdateGenerativeQuestionConfigRequest() + requests.generative_question_config.catalog = "catalog_value" + requests.generative_question_config.facet = "facet_value" + + request = retail_v2.BatchUpdateGenerativeQuestionConfigsRequest( + requests=requests, + ) + + # Make the request + response = await client.batch_update_generative_question_configs(request=request) + + # Handle the response + print(response) + +# [END retail_v2_generated_GenerativeQuestionService_BatchUpdateGenerativeQuestionConfigs_async] diff --git a/packages/google-cloud-retail/samples/generated_samples/retail_v2_generated_generative_question_service_batch_update_generative_question_configs_sync.py b/packages/google-cloud-retail/samples/generated_samples/retail_v2_generated_generative_question_service_batch_update_generative_question_configs_sync.py new file mode 100644 index 000000000000..b138f0e025bb --- /dev/null +++ b/packages/google-cloud-retail/samples/generated_samples/retail_v2_generated_generative_question_service_batch_update_generative_question_configs_sync.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for BatchUpdateGenerativeQuestionConfigs +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-retail + + +# [START retail_v2_generated_GenerativeQuestionService_BatchUpdateGenerativeQuestionConfigs_sync] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import retail_v2 + + +def sample_batch_update_generative_question_configs(): + # Create a client + client = retail_v2.GenerativeQuestionServiceClient() + + # Initialize request argument(s) + requests = retail_v2.UpdateGenerativeQuestionConfigRequest() + requests.generative_question_config.catalog = "catalog_value" + requests.generative_question_config.facet = "facet_value" + + request = retail_v2.BatchUpdateGenerativeQuestionConfigsRequest( + requests=requests, + ) + + # Make the request + response = client.batch_update_generative_question_configs(request=request) + + # Handle the response + print(response) + +# [END retail_v2_generated_GenerativeQuestionService_BatchUpdateGenerativeQuestionConfigs_sync] diff --git a/packages/google-cloud-retail/samples/generated_samples/retail_v2_generated_generative_question_service_get_generative_questions_feature_config_async.py b/packages/google-cloud-retail/samples/generated_samples/retail_v2_generated_generative_question_service_get_generative_questions_feature_config_async.py new file mode 100644 index 000000000000..fc9ab137d821 --- /dev/null +++ b/packages/google-cloud-retail/samples/generated_samples/retail_v2_generated_generative_question_service_get_generative_questions_feature_config_async.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for GetGenerativeQuestionsFeatureConfig +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-retail + + +# [START retail_v2_generated_GenerativeQuestionService_GetGenerativeQuestionsFeatureConfig_async] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import retail_v2 + + +async def sample_get_generative_questions_feature_config(): + # Create a client + client = retail_v2.GenerativeQuestionServiceAsyncClient() + + # Initialize request argument(s) + request = retail_v2.GetGenerativeQuestionsFeatureConfigRequest( + catalog="catalog_value", + ) + + # Make the request + response = await client.get_generative_questions_feature_config(request=request) + + # Handle the response + print(response) + +# [END retail_v2_generated_GenerativeQuestionService_GetGenerativeQuestionsFeatureConfig_async] diff --git a/packages/google-cloud-retail/samples/generated_samples/retail_v2_generated_generative_question_service_get_generative_questions_feature_config_sync.py b/packages/google-cloud-retail/samples/generated_samples/retail_v2_generated_generative_question_service_get_generative_questions_feature_config_sync.py new file mode 100644 index 000000000000..92fa963b7ca6 --- /dev/null +++ b/packages/google-cloud-retail/samples/generated_samples/retail_v2_generated_generative_question_service_get_generative_questions_feature_config_sync.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for GetGenerativeQuestionsFeatureConfig +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-retail + + +# [START retail_v2_generated_GenerativeQuestionService_GetGenerativeQuestionsFeatureConfig_sync] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import retail_v2 + + +def sample_get_generative_questions_feature_config(): + # Create a client + client = retail_v2.GenerativeQuestionServiceClient() + + # Initialize request argument(s) + request = retail_v2.GetGenerativeQuestionsFeatureConfigRequest( + catalog="catalog_value", + ) + + # Make the request + response = client.get_generative_questions_feature_config(request=request) + + # Handle the response + print(response) + +# [END retail_v2_generated_GenerativeQuestionService_GetGenerativeQuestionsFeatureConfig_sync] diff --git a/packages/google-cloud-retail/samples/generated_samples/retail_v2_generated_generative_question_service_list_generative_question_configs_async.py b/packages/google-cloud-retail/samples/generated_samples/retail_v2_generated_generative_question_service_list_generative_question_configs_async.py new file mode 100644 index 000000000000..cb7119b008d8 --- /dev/null +++ b/packages/google-cloud-retail/samples/generated_samples/retail_v2_generated_generative_question_service_list_generative_question_configs_async.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for ListGenerativeQuestionConfigs +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-retail + + +# [START retail_v2_generated_GenerativeQuestionService_ListGenerativeQuestionConfigs_async] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import retail_v2 + + +async def sample_list_generative_question_configs(): + # Create a client + client = retail_v2.GenerativeQuestionServiceAsyncClient() + + # Initialize request argument(s) + request = retail_v2.ListGenerativeQuestionConfigsRequest( + parent="parent_value", + ) + + # Make the request + response = await client.list_generative_question_configs(request=request) + + # Handle the response + print(response) + +# [END retail_v2_generated_GenerativeQuestionService_ListGenerativeQuestionConfigs_async] diff --git a/packages/google-cloud-retail/samples/generated_samples/retail_v2_generated_generative_question_service_list_generative_question_configs_sync.py b/packages/google-cloud-retail/samples/generated_samples/retail_v2_generated_generative_question_service_list_generative_question_configs_sync.py new file mode 100644 index 000000000000..4e4acdd3bc5e --- /dev/null +++ b/packages/google-cloud-retail/samples/generated_samples/retail_v2_generated_generative_question_service_list_generative_question_configs_sync.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for ListGenerativeQuestionConfigs +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-retail + + +# [START retail_v2_generated_GenerativeQuestionService_ListGenerativeQuestionConfigs_sync] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import retail_v2 + + +def sample_list_generative_question_configs(): + # Create a client + client = retail_v2.GenerativeQuestionServiceClient() + + # Initialize request argument(s) + request = retail_v2.ListGenerativeQuestionConfigsRequest( + parent="parent_value", + ) + + # Make the request + response = client.list_generative_question_configs(request=request) + + # Handle the response + print(response) + +# [END retail_v2_generated_GenerativeQuestionService_ListGenerativeQuestionConfigs_sync] diff --git a/packages/google-cloud-retail/samples/generated_samples/retail_v2_generated_generative_question_service_update_generative_question_config_async.py b/packages/google-cloud-retail/samples/generated_samples/retail_v2_generated_generative_question_service_update_generative_question_config_async.py new file mode 100644 index 000000000000..418f389b9b8e --- /dev/null +++ b/packages/google-cloud-retail/samples/generated_samples/retail_v2_generated_generative_question_service_update_generative_question_config_async.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for UpdateGenerativeQuestionConfig +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-retail + + +# [START retail_v2_generated_GenerativeQuestionService_UpdateGenerativeQuestionConfig_async] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import retail_v2 + + +async def sample_update_generative_question_config(): + # Create a client + client = retail_v2.GenerativeQuestionServiceAsyncClient() + + # Initialize request argument(s) + generative_question_config = retail_v2.GenerativeQuestionConfig() + generative_question_config.catalog = "catalog_value" + generative_question_config.facet = "facet_value" + + request = retail_v2.UpdateGenerativeQuestionConfigRequest( + generative_question_config=generative_question_config, + ) + + # Make the request + response = await client.update_generative_question_config(request=request) + + # Handle the response + print(response) + +# [END retail_v2_generated_GenerativeQuestionService_UpdateGenerativeQuestionConfig_async] diff --git a/packages/google-cloud-retail/samples/generated_samples/retail_v2_generated_generative_question_service_update_generative_question_config_sync.py b/packages/google-cloud-retail/samples/generated_samples/retail_v2_generated_generative_question_service_update_generative_question_config_sync.py new file mode 100644 index 000000000000..ef6c8d3c5215 --- /dev/null +++ b/packages/google-cloud-retail/samples/generated_samples/retail_v2_generated_generative_question_service_update_generative_question_config_sync.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for UpdateGenerativeQuestionConfig +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-retail + + +# [START retail_v2_generated_GenerativeQuestionService_UpdateGenerativeQuestionConfig_sync] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import retail_v2 + + +def sample_update_generative_question_config(): + # Create a client + client = retail_v2.GenerativeQuestionServiceClient() + + # Initialize request argument(s) + generative_question_config = retail_v2.GenerativeQuestionConfig() + generative_question_config.catalog = "catalog_value" + generative_question_config.facet = "facet_value" + + request = retail_v2.UpdateGenerativeQuestionConfigRequest( + generative_question_config=generative_question_config, + ) + + # Make the request + response = client.update_generative_question_config(request=request) + + # Handle the response + print(response) + +# [END retail_v2_generated_GenerativeQuestionService_UpdateGenerativeQuestionConfig_sync] diff --git a/packages/google-cloud-retail/samples/generated_samples/retail_v2_generated_generative_question_service_update_generative_questions_feature_config_async.py b/packages/google-cloud-retail/samples/generated_samples/retail_v2_generated_generative_question_service_update_generative_questions_feature_config_async.py new file mode 100644 index 000000000000..f37d12ba102f --- /dev/null +++ b/packages/google-cloud-retail/samples/generated_samples/retail_v2_generated_generative_question_service_update_generative_questions_feature_config_async.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for UpdateGenerativeQuestionsFeatureConfig +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-retail + + +# [START retail_v2_generated_GenerativeQuestionService_UpdateGenerativeQuestionsFeatureConfig_async] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import retail_v2 + + +async def sample_update_generative_questions_feature_config(): + # Create a client + client = retail_v2.GenerativeQuestionServiceAsyncClient() + + # Initialize request argument(s) + generative_questions_feature_config = retail_v2.GenerativeQuestionsFeatureConfig() + generative_questions_feature_config.catalog = "catalog_value" + + request = retail_v2.UpdateGenerativeQuestionsFeatureConfigRequest( + generative_questions_feature_config=generative_questions_feature_config, + ) + + # Make the request + response = await client.update_generative_questions_feature_config(request=request) + + # Handle the response + print(response) + +# [END retail_v2_generated_GenerativeQuestionService_UpdateGenerativeQuestionsFeatureConfig_async] diff --git a/packages/google-cloud-retail/samples/generated_samples/retail_v2_generated_generative_question_service_update_generative_questions_feature_config_sync.py b/packages/google-cloud-retail/samples/generated_samples/retail_v2_generated_generative_question_service_update_generative_questions_feature_config_sync.py new file mode 100644 index 000000000000..d065ca0cba82 --- /dev/null +++ b/packages/google-cloud-retail/samples/generated_samples/retail_v2_generated_generative_question_service_update_generative_questions_feature_config_sync.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for UpdateGenerativeQuestionsFeatureConfig +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-retail + + +# [START retail_v2_generated_GenerativeQuestionService_UpdateGenerativeQuestionsFeatureConfig_sync] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import retail_v2 + + +def sample_update_generative_questions_feature_config(): + # Create a client + client = retail_v2.GenerativeQuestionServiceClient() + + # Initialize request argument(s) + generative_questions_feature_config = retail_v2.GenerativeQuestionsFeatureConfig() + generative_questions_feature_config.catalog = "catalog_value" + + request = retail_v2.UpdateGenerativeQuestionsFeatureConfigRequest( + generative_questions_feature_config=generative_questions_feature_config, + ) + + # Make the request + response = client.update_generative_questions_feature_config(request=request) + + # Handle the response + print(response) + +# [END retail_v2_generated_GenerativeQuestionService_UpdateGenerativeQuestionsFeatureConfig_sync] diff --git a/packages/google-cloud-retail/samples/generated_samples/retail_v2alpha_generated_generative_question_service_batch_update_generative_question_configs_async.py b/packages/google-cloud-retail/samples/generated_samples/retail_v2alpha_generated_generative_question_service_batch_update_generative_question_configs_async.py new file mode 100644 index 000000000000..acd64ee96856 --- /dev/null +++ b/packages/google-cloud-retail/samples/generated_samples/retail_v2alpha_generated_generative_question_service_batch_update_generative_question_configs_async.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for BatchUpdateGenerativeQuestionConfigs +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-retail + + +# [START retail_v2alpha_generated_GenerativeQuestionService_BatchUpdateGenerativeQuestionConfigs_async] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import retail_v2alpha + + +async def sample_batch_update_generative_question_configs(): + # Create a client + client = retail_v2alpha.GenerativeQuestionServiceAsyncClient() + + # Initialize request argument(s) + requests = retail_v2alpha.UpdateGenerativeQuestionConfigRequest() + requests.generative_question_config.catalog = "catalog_value" + requests.generative_question_config.facet = "facet_value" + + request = retail_v2alpha.BatchUpdateGenerativeQuestionConfigsRequest( + requests=requests, + ) + + # Make the request + response = await client.batch_update_generative_question_configs(request=request) + + # Handle the response + print(response) + +# [END retail_v2alpha_generated_GenerativeQuestionService_BatchUpdateGenerativeQuestionConfigs_async] diff --git a/packages/google-cloud-retail/samples/generated_samples/retail_v2alpha_generated_generative_question_service_batch_update_generative_question_configs_sync.py b/packages/google-cloud-retail/samples/generated_samples/retail_v2alpha_generated_generative_question_service_batch_update_generative_question_configs_sync.py new file mode 100644 index 000000000000..1a3c6f6180ca --- /dev/null +++ b/packages/google-cloud-retail/samples/generated_samples/retail_v2alpha_generated_generative_question_service_batch_update_generative_question_configs_sync.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for BatchUpdateGenerativeQuestionConfigs +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-retail + + +# [START retail_v2alpha_generated_GenerativeQuestionService_BatchUpdateGenerativeQuestionConfigs_sync] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import retail_v2alpha + + +def sample_batch_update_generative_question_configs(): + # Create a client + client = retail_v2alpha.GenerativeQuestionServiceClient() + + # Initialize request argument(s) + requests = retail_v2alpha.UpdateGenerativeQuestionConfigRequest() + requests.generative_question_config.catalog = "catalog_value" + requests.generative_question_config.facet = "facet_value" + + request = retail_v2alpha.BatchUpdateGenerativeQuestionConfigsRequest( + requests=requests, + ) + + # Make the request + response = client.batch_update_generative_question_configs(request=request) + + # Handle the response + print(response) + +# [END retail_v2alpha_generated_GenerativeQuestionService_BatchUpdateGenerativeQuestionConfigs_sync] diff --git a/packages/google-cloud-retail/samples/generated_samples/retail_v2alpha_generated_generative_question_service_get_generative_questions_feature_config_async.py b/packages/google-cloud-retail/samples/generated_samples/retail_v2alpha_generated_generative_question_service_get_generative_questions_feature_config_async.py new file mode 100644 index 000000000000..44cc60d841a5 --- /dev/null +++ b/packages/google-cloud-retail/samples/generated_samples/retail_v2alpha_generated_generative_question_service_get_generative_questions_feature_config_async.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for GetGenerativeQuestionsFeatureConfig +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-retail + + +# [START retail_v2alpha_generated_GenerativeQuestionService_GetGenerativeQuestionsFeatureConfig_async] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import retail_v2alpha + + +async def sample_get_generative_questions_feature_config(): + # Create a client + client = retail_v2alpha.GenerativeQuestionServiceAsyncClient() + + # Initialize request argument(s) + request = retail_v2alpha.GetGenerativeQuestionsFeatureConfigRequest( + catalog="catalog_value", + ) + + # Make the request + response = await client.get_generative_questions_feature_config(request=request) + + # Handle the response + print(response) + +# [END retail_v2alpha_generated_GenerativeQuestionService_GetGenerativeQuestionsFeatureConfig_async] diff --git a/packages/google-cloud-retail/samples/generated_samples/retail_v2alpha_generated_generative_question_service_get_generative_questions_feature_config_sync.py b/packages/google-cloud-retail/samples/generated_samples/retail_v2alpha_generated_generative_question_service_get_generative_questions_feature_config_sync.py new file mode 100644 index 000000000000..b186f46ea3e6 --- /dev/null +++ b/packages/google-cloud-retail/samples/generated_samples/retail_v2alpha_generated_generative_question_service_get_generative_questions_feature_config_sync.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for GetGenerativeQuestionsFeatureConfig +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-retail + + +# [START retail_v2alpha_generated_GenerativeQuestionService_GetGenerativeQuestionsFeatureConfig_sync] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import retail_v2alpha + + +def sample_get_generative_questions_feature_config(): + # Create a client + client = retail_v2alpha.GenerativeQuestionServiceClient() + + # Initialize request argument(s) + request = retail_v2alpha.GetGenerativeQuestionsFeatureConfigRequest( + catalog="catalog_value", + ) + + # Make the request + response = client.get_generative_questions_feature_config(request=request) + + # Handle the response + print(response) + +# [END retail_v2alpha_generated_GenerativeQuestionService_GetGenerativeQuestionsFeatureConfig_sync] diff --git a/packages/google-cloud-retail/samples/generated_samples/retail_v2alpha_generated_generative_question_service_list_generative_question_configs_async.py b/packages/google-cloud-retail/samples/generated_samples/retail_v2alpha_generated_generative_question_service_list_generative_question_configs_async.py new file mode 100644 index 000000000000..a8485391af60 --- /dev/null +++ b/packages/google-cloud-retail/samples/generated_samples/retail_v2alpha_generated_generative_question_service_list_generative_question_configs_async.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for ListGenerativeQuestionConfigs +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-retail + + +# [START retail_v2alpha_generated_GenerativeQuestionService_ListGenerativeQuestionConfigs_async] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import retail_v2alpha + + +async def sample_list_generative_question_configs(): + # Create a client + client = retail_v2alpha.GenerativeQuestionServiceAsyncClient() + + # Initialize request argument(s) + request = retail_v2alpha.ListGenerativeQuestionConfigsRequest( + parent="parent_value", + ) + + # Make the request + response = await client.list_generative_question_configs(request=request) + + # Handle the response + print(response) + +# [END retail_v2alpha_generated_GenerativeQuestionService_ListGenerativeQuestionConfigs_async] diff --git a/packages/google-cloud-retail/samples/generated_samples/retail_v2alpha_generated_generative_question_service_list_generative_question_configs_sync.py b/packages/google-cloud-retail/samples/generated_samples/retail_v2alpha_generated_generative_question_service_list_generative_question_configs_sync.py new file mode 100644 index 000000000000..c2c255cf6dfd --- /dev/null +++ b/packages/google-cloud-retail/samples/generated_samples/retail_v2alpha_generated_generative_question_service_list_generative_question_configs_sync.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for ListGenerativeQuestionConfigs +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-retail + + +# [START retail_v2alpha_generated_GenerativeQuestionService_ListGenerativeQuestionConfigs_sync] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import retail_v2alpha + + +def sample_list_generative_question_configs(): + # Create a client + client = retail_v2alpha.GenerativeQuestionServiceClient() + + # Initialize request argument(s) + request = retail_v2alpha.ListGenerativeQuestionConfigsRequest( + parent="parent_value", + ) + + # Make the request + response = client.list_generative_question_configs(request=request) + + # Handle the response + print(response) + +# [END retail_v2alpha_generated_GenerativeQuestionService_ListGenerativeQuestionConfigs_sync] diff --git a/packages/google-cloud-retail/samples/generated_samples/retail_v2alpha_generated_generative_question_service_update_generative_question_config_async.py b/packages/google-cloud-retail/samples/generated_samples/retail_v2alpha_generated_generative_question_service_update_generative_question_config_async.py new file mode 100644 index 000000000000..216632d30404 --- /dev/null +++ b/packages/google-cloud-retail/samples/generated_samples/retail_v2alpha_generated_generative_question_service_update_generative_question_config_async.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for UpdateGenerativeQuestionConfig +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-retail + + +# [START retail_v2alpha_generated_GenerativeQuestionService_UpdateGenerativeQuestionConfig_async] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import retail_v2alpha + + +async def sample_update_generative_question_config(): + # Create a client + client = retail_v2alpha.GenerativeQuestionServiceAsyncClient() + + # Initialize request argument(s) + generative_question_config = retail_v2alpha.GenerativeQuestionConfig() + generative_question_config.catalog = "catalog_value" + generative_question_config.facet = "facet_value" + + request = retail_v2alpha.UpdateGenerativeQuestionConfigRequest( + generative_question_config=generative_question_config, + ) + + # Make the request + response = await client.update_generative_question_config(request=request) + + # Handle the response + print(response) + +# [END retail_v2alpha_generated_GenerativeQuestionService_UpdateGenerativeQuestionConfig_async] diff --git a/packages/google-cloud-retail/samples/generated_samples/retail_v2alpha_generated_generative_question_service_update_generative_question_config_sync.py b/packages/google-cloud-retail/samples/generated_samples/retail_v2alpha_generated_generative_question_service_update_generative_question_config_sync.py new file mode 100644 index 000000000000..c92ad179175d --- /dev/null +++ b/packages/google-cloud-retail/samples/generated_samples/retail_v2alpha_generated_generative_question_service_update_generative_question_config_sync.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for UpdateGenerativeQuestionConfig +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-retail + + +# [START retail_v2alpha_generated_GenerativeQuestionService_UpdateGenerativeQuestionConfig_sync] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import retail_v2alpha + + +def sample_update_generative_question_config(): + # Create a client + client = retail_v2alpha.GenerativeQuestionServiceClient() + + # Initialize request argument(s) + generative_question_config = retail_v2alpha.GenerativeQuestionConfig() + generative_question_config.catalog = "catalog_value" + generative_question_config.facet = "facet_value" + + request = retail_v2alpha.UpdateGenerativeQuestionConfigRequest( + generative_question_config=generative_question_config, + ) + + # Make the request + response = client.update_generative_question_config(request=request) + + # Handle the response + print(response) + +# [END retail_v2alpha_generated_GenerativeQuestionService_UpdateGenerativeQuestionConfig_sync] diff --git a/packages/google-cloud-retail/samples/generated_samples/retail_v2alpha_generated_generative_question_service_update_generative_questions_feature_config_async.py b/packages/google-cloud-retail/samples/generated_samples/retail_v2alpha_generated_generative_question_service_update_generative_questions_feature_config_async.py new file mode 100644 index 000000000000..f2dad891180c --- /dev/null +++ b/packages/google-cloud-retail/samples/generated_samples/retail_v2alpha_generated_generative_question_service_update_generative_questions_feature_config_async.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for UpdateGenerativeQuestionsFeatureConfig +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-retail + + +# [START retail_v2alpha_generated_GenerativeQuestionService_UpdateGenerativeQuestionsFeatureConfig_async] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import retail_v2alpha + + +async def sample_update_generative_questions_feature_config(): + # Create a client + client = retail_v2alpha.GenerativeQuestionServiceAsyncClient() + + # Initialize request argument(s) + generative_questions_feature_config = retail_v2alpha.GenerativeQuestionsFeatureConfig() + generative_questions_feature_config.catalog = "catalog_value" + + request = retail_v2alpha.UpdateGenerativeQuestionsFeatureConfigRequest( + generative_questions_feature_config=generative_questions_feature_config, + ) + + # Make the request + response = await client.update_generative_questions_feature_config(request=request) + + # Handle the response + print(response) + +# [END retail_v2alpha_generated_GenerativeQuestionService_UpdateGenerativeQuestionsFeatureConfig_async] diff --git a/packages/google-cloud-retail/samples/generated_samples/retail_v2alpha_generated_generative_question_service_update_generative_questions_feature_config_sync.py b/packages/google-cloud-retail/samples/generated_samples/retail_v2alpha_generated_generative_question_service_update_generative_questions_feature_config_sync.py new file mode 100644 index 000000000000..4847990d0bad --- /dev/null +++ b/packages/google-cloud-retail/samples/generated_samples/retail_v2alpha_generated_generative_question_service_update_generative_questions_feature_config_sync.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for UpdateGenerativeQuestionsFeatureConfig +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-retail + + +# [START retail_v2alpha_generated_GenerativeQuestionService_UpdateGenerativeQuestionsFeatureConfig_sync] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import retail_v2alpha + + +def sample_update_generative_questions_feature_config(): + # Create a client + client = retail_v2alpha.GenerativeQuestionServiceClient() + + # Initialize request argument(s) + generative_questions_feature_config = retail_v2alpha.GenerativeQuestionsFeatureConfig() + generative_questions_feature_config.catalog = "catalog_value" + + request = retail_v2alpha.UpdateGenerativeQuestionsFeatureConfigRequest( + generative_questions_feature_config=generative_questions_feature_config, + ) + + # Make the request + response = client.update_generative_questions_feature_config(request=request) + + # Handle the response + print(response) + +# [END retail_v2alpha_generated_GenerativeQuestionService_UpdateGenerativeQuestionsFeatureConfig_sync] diff --git a/packages/google-cloud-retail/samples/generated_samples/retail_v2alpha_generated_product_service_export_products_async.py b/packages/google-cloud-retail/samples/generated_samples/retail_v2alpha_generated_product_service_export_products_async.py new file mode 100644 index 000000000000..154af3ce9328 --- /dev/null +++ b/packages/google-cloud-retail/samples/generated_samples/retail_v2alpha_generated_product_service_export_products_async.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for ExportProducts +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-retail + + +# [START retail_v2alpha_generated_ProductService_ExportProducts_async] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import retail_v2alpha + + +async def sample_export_products(): + # Create a client + client = retail_v2alpha.ProductServiceAsyncClient() + + # Initialize request argument(s) + output_config = retail_v2alpha.OutputConfig() + output_config.gcs_destination.output_uri_prefix = "output_uri_prefix_value" + + request = retail_v2alpha.ExportProductsRequest( + parent="parent_value", + output_config=output_config, + ) + + # Make the request + operation = client.export_products(request=request) + + print("Waiting for operation to complete...") + + response = (await operation).result() + + # Handle the response + print(response) + +# [END retail_v2alpha_generated_ProductService_ExportProducts_async] diff --git a/packages/google-cloud-retail/samples/generated_samples/retail_v2alpha_generated_product_service_export_products_sync.py b/packages/google-cloud-retail/samples/generated_samples/retail_v2alpha_generated_product_service_export_products_sync.py new file mode 100644 index 000000000000..18b15468336f --- /dev/null +++ b/packages/google-cloud-retail/samples/generated_samples/retail_v2alpha_generated_product_service_export_products_sync.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for ExportProducts +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-retail + + +# [START retail_v2alpha_generated_ProductService_ExportProducts_sync] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import retail_v2alpha + + +def sample_export_products(): + # Create a client + client = retail_v2alpha.ProductServiceClient() + + # Initialize request argument(s) + output_config = retail_v2alpha.OutputConfig() + output_config.gcs_destination.output_uri_prefix = "output_uri_prefix_value" + + request = retail_v2alpha.ExportProductsRequest( + parent="parent_value", + output_config=output_config, + ) + + # Make the request + operation = client.export_products(request=request) + + print("Waiting for operation to complete...") + + response = operation.result() + + # Handle the response + print(response) + +# [END retail_v2alpha_generated_ProductService_ExportProducts_sync] diff --git a/packages/google-cloud-retail/samples/generated_samples/retail_v2alpha_generated_user_event_service_export_user_events_async.py b/packages/google-cloud-retail/samples/generated_samples/retail_v2alpha_generated_user_event_service_export_user_events_async.py new file mode 100644 index 000000000000..b358e623b350 --- /dev/null +++ b/packages/google-cloud-retail/samples/generated_samples/retail_v2alpha_generated_user_event_service_export_user_events_async.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for ExportUserEvents +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-retail + + +# [START retail_v2alpha_generated_UserEventService_ExportUserEvents_async] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import retail_v2alpha + + +async def sample_export_user_events(): + # Create a client + client = retail_v2alpha.UserEventServiceAsyncClient() + + # Initialize request argument(s) + output_config = retail_v2alpha.OutputConfig() + output_config.gcs_destination.output_uri_prefix = "output_uri_prefix_value" + + request = retail_v2alpha.ExportUserEventsRequest( + parent="parent_value", + output_config=output_config, + ) + + # Make the request + operation = client.export_user_events(request=request) + + print("Waiting for operation to complete...") + + response = (await operation).result() + + # Handle the response + print(response) + +# [END retail_v2alpha_generated_UserEventService_ExportUserEvents_async] diff --git a/packages/google-cloud-retail/samples/generated_samples/retail_v2alpha_generated_user_event_service_export_user_events_sync.py b/packages/google-cloud-retail/samples/generated_samples/retail_v2alpha_generated_user_event_service_export_user_events_sync.py new file mode 100644 index 000000000000..7cd4b0cf92f3 --- /dev/null +++ b/packages/google-cloud-retail/samples/generated_samples/retail_v2alpha_generated_user_event_service_export_user_events_sync.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for ExportUserEvents +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-retail + + +# [START retail_v2alpha_generated_UserEventService_ExportUserEvents_sync] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import retail_v2alpha + + +def sample_export_user_events(): + # Create a client + client = retail_v2alpha.UserEventServiceClient() + + # Initialize request argument(s) + output_config = retail_v2alpha.OutputConfig() + output_config.gcs_destination.output_uri_prefix = "output_uri_prefix_value" + + request = retail_v2alpha.ExportUserEventsRequest( + parent="parent_value", + output_config=output_config, + ) + + # Make the request + operation = client.export_user_events(request=request) + + print("Waiting for operation to complete...") + + response = operation.result() + + # Handle the response + print(response) + +# [END retail_v2alpha_generated_UserEventService_ExportUserEvents_sync] diff --git a/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_generative_question_service_batch_update_generative_question_configs_async.py b/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_generative_question_service_batch_update_generative_question_configs_async.py new file mode 100644 index 000000000000..081a0a7f4c1f --- /dev/null +++ b/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_generative_question_service_batch_update_generative_question_configs_async.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for BatchUpdateGenerativeQuestionConfigs +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-retail + + +# [START retail_v2beta_generated_GenerativeQuestionService_BatchUpdateGenerativeQuestionConfigs_async] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import retail_v2beta + + +async def sample_batch_update_generative_question_configs(): + # Create a client + client = retail_v2beta.GenerativeQuestionServiceAsyncClient() + + # Initialize request argument(s) + requests = retail_v2beta.UpdateGenerativeQuestionConfigRequest() + requests.generative_question_config.catalog = "catalog_value" + requests.generative_question_config.facet = "facet_value" + + request = retail_v2beta.BatchUpdateGenerativeQuestionConfigsRequest( + requests=requests, + ) + + # Make the request + response = await client.batch_update_generative_question_configs(request=request) + + # Handle the response + print(response) + +# [END retail_v2beta_generated_GenerativeQuestionService_BatchUpdateGenerativeQuestionConfigs_async] diff --git a/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_generative_question_service_batch_update_generative_question_configs_sync.py b/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_generative_question_service_batch_update_generative_question_configs_sync.py new file mode 100644 index 000000000000..7970ba0adf4b --- /dev/null +++ b/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_generative_question_service_batch_update_generative_question_configs_sync.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for BatchUpdateGenerativeQuestionConfigs +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-retail + + +# [START retail_v2beta_generated_GenerativeQuestionService_BatchUpdateGenerativeQuestionConfigs_sync] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import retail_v2beta + + +def sample_batch_update_generative_question_configs(): + # Create a client + client = retail_v2beta.GenerativeQuestionServiceClient() + + # Initialize request argument(s) + requests = retail_v2beta.UpdateGenerativeQuestionConfigRequest() + requests.generative_question_config.catalog = "catalog_value" + requests.generative_question_config.facet = "facet_value" + + request = retail_v2beta.BatchUpdateGenerativeQuestionConfigsRequest( + requests=requests, + ) + + # Make the request + response = client.batch_update_generative_question_configs(request=request) + + # Handle the response + print(response) + +# [END retail_v2beta_generated_GenerativeQuestionService_BatchUpdateGenerativeQuestionConfigs_sync] diff --git a/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_generative_question_service_get_generative_questions_feature_config_async.py b/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_generative_question_service_get_generative_questions_feature_config_async.py new file mode 100644 index 000000000000..b536aa4310e0 --- /dev/null +++ b/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_generative_question_service_get_generative_questions_feature_config_async.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for GetGenerativeQuestionsFeatureConfig +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-retail + + +# [START retail_v2beta_generated_GenerativeQuestionService_GetGenerativeQuestionsFeatureConfig_async] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import retail_v2beta + + +async def sample_get_generative_questions_feature_config(): + # Create a client + client = retail_v2beta.GenerativeQuestionServiceAsyncClient() + + # Initialize request argument(s) + request = retail_v2beta.GetGenerativeQuestionsFeatureConfigRequest( + catalog="catalog_value", + ) + + # Make the request + response = await client.get_generative_questions_feature_config(request=request) + + # Handle the response + print(response) + +# [END retail_v2beta_generated_GenerativeQuestionService_GetGenerativeQuestionsFeatureConfig_async] diff --git a/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_generative_question_service_get_generative_questions_feature_config_sync.py b/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_generative_question_service_get_generative_questions_feature_config_sync.py new file mode 100644 index 000000000000..a2a9dba37775 --- /dev/null +++ b/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_generative_question_service_get_generative_questions_feature_config_sync.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for GetGenerativeQuestionsFeatureConfig +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-retail + + +# [START retail_v2beta_generated_GenerativeQuestionService_GetGenerativeQuestionsFeatureConfig_sync] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import retail_v2beta + + +def sample_get_generative_questions_feature_config(): + # Create a client + client = retail_v2beta.GenerativeQuestionServiceClient() + + # Initialize request argument(s) + request = retail_v2beta.GetGenerativeQuestionsFeatureConfigRequest( + catalog="catalog_value", + ) + + # Make the request + response = client.get_generative_questions_feature_config(request=request) + + # Handle the response + print(response) + +# [END retail_v2beta_generated_GenerativeQuestionService_GetGenerativeQuestionsFeatureConfig_sync] diff --git a/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_generative_question_service_list_generative_question_configs_async.py b/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_generative_question_service_list_generative_question_configs_async.py new file mode 100644 index 000000000000..9e9dd888e09e --- /dev/null +++ b/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_generative_question_service_list_generative_question_configs_async.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for ListGenerativeQuestionConfigs +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-retail + + +# [START retail_v2beta_generated_GenerativeQuestionService_ListGenerativeQuestionConfigs_async] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import retail_v2beta + + +async def sample_list_generative_question_configs(): + # Create a client + client = retail_v2beta.GenerativeQuestionServiceAsyncClient() + + # Initialize request argument(s) + request = retail_v2beta.ListGenerativeQuestionConfigsRequest( + parent="parent_value", + ) + + # Make the request + response = await client.list_generative_question_configs(request=request) + + # Handle the response + print(response) + +# [END retail_v2beta_generated_GenerativeQuestionService_ListGenerativeQuestionConfigs_async] diff --git a/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_generative_question_service_list_generative_question_configs_sync.py b/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_generative_question_service_list_generative_question_configs_sync.py new file mode 100644 index 000000000000..545da8125c35 --- /dev/null +++ b/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_generative_question_service_list_generative_question_configs_sync.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for ListGenerativeQuestionConfigs +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-retail + + +# [START retail_v2beta_generated_GenerativeQuestionService_ListGenerativeQuestionConfigs_sync] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import retail_v2beta + + +def sample_list_generative_question_configs(): + # Create a client + client = retail_v2beta.GenerativeQuestionServiceClient() + + # Initialize request argument(s) + request = retail_v2beta.ListGenerativeQuestionConfigsRequest( + parent="parent_value", + ) + + # Make the request + response = client.list_generative_question_configs(request=request) + + # Handle the response + print(response) + +# [END retail_v2beta_generated_GenerativeQuestionService_ListGenerativeQuestionConfigs_sync] diff --git a/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_generative_question_service_update_generative_question_config_async.py b/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_generative_question_service_update_generative_question_config_async.py new file mode 100644 index 000000000000..9e971453d2cb --- /dev/null +++ b/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_generative_question_service_update_generative_question_config_async.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for UpdateGenerativeQuestionConfig +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-retail + + +# [START retail_v2beta_generated_GenerativeQuestionService_UpdateGenerativeQuestionConfig_async] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import retail_v2beta + + +async def sample_update_generative_question_config(): + # Create a client + client = retail_v2beta.GenerativeQuestionServiceAsyncClient() + + # Initialize request argument(s) + generative_question_config = retail_v2beta.GenerativeQuestionConfig() + generative_question_config.catalog = "catalog_value" + generative_question_config.facet = "facet_value" + + request = retail_v2beta.UpdateGenerativeQuestionConfigRequest( + generative_question_config=generative_question_config, + ) + + # Make the request + response = await client.update_generative_question_config(request=request) + + # Handle the response + print(response) + +# [END retail_v2beta_generated_GenerativeQuestionService_UpdateGenerativeQuestionConfig_async] diff --git a/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_generative_question_service_update_generative_question_config_sync.py b/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_generative_question_service_update_generative_question_config_sync.py new file mode 100644 index 000000000000..fc427fc5ceb2 --- /dev/null +++ b/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_generative_question_service_update_generative_question_config_sync.py @@ -0,0 +1,56 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for UpdateGenerativeQuestionConfig +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-retail + + +# [START retail_v2beta_generated_GenerativeQuestionService_UpdateGenerativeQuestionConfig_sync] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import retail_v2beta + + +def sample_update_generative_question_config(): + # Create a client + client = retail_v2beta.GenerativeQuestionServiceClient() + + # Initialize request argument(s) + generative_question_config = retail_v2beta.GenerativeQuestionConfig() + generative_question_config.catalog = "catalog_value" + generative_question_config.facet = "facet_value" + + request = retail_v2beta.UpdateGenerativeQuestionConfigRequest( + generative_question_config=generative_question_config, + ) + + # Make the request + response = client.update_generative_question_config(request=request) + + # Handle the response + print(response) + +# [END retail_v2beta_generated_GenerativeQuestionService_UpdateGenerativeQuestionConfig_sync] diff --git a/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_generative_question_service_update_generative_questions_feature_config_async.py b/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_generative_question_service_update_generative_questions_feature_config_async.py new file mode 100644 index 000000000000..7267d0fd6769 --- /dev/null +++ b/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_generative_question_service_update_generative_questions_feature_config_async.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for UpdateGenerativeQuestionsFeatureConfig +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-retail + + +# [START retail_v2beta_generated_GenerativeQuestionService_UpdateGenerativeQuestionsFeatureConfig_async] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import retail_v2beta + + +async def sample_update_generative_questions_feature_config(): + # Create a client + client = retail_v2beta.GenerativeQuestionServiceAsyncClient() + + # Initialize request argument(s) + generative_questions_feature_config = retail_v2beta.GenerativeQuestionsFeatureConfig() + generative_questions_feature_config.catalog = "catalog_value" + + request = retail_v2beta.UpdateGenerativeQuestionsFeatureConfigRequest( + generative_questions_feature_config=generative_questions_feature_config, + ) + + # Make the request + response = await client.update_generative_questions_feature_config(request=request) + + # Handle the response + print(response) + +# [END retail_v2beta_generated_GenerativeQuestionService_UpdateGenerativeQuestionsFeatureConfig_async] diff --git a/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_generative_question_service_update_generative_questions_feature_config_sync.py b/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_generative_question_service_update_generative_questions_feature_config_sync.py new file mode 100644 index 000000000000..d3db571b0cbf --- /dev/null +++ b/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_generative_question_service_update_generative_questions_feature_config_sync.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for UpdateGenerativeQuestionsFeatureConfig +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-retail + + +# [START retail_v2beta_generated_GenerativeQuestionService_UpdateGenerativeQuestionsFeatureConfig_sync] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import retail_v2beta + + +def sample_update_generative_questions_feature_config(): + # Create a client + client = retail_v2beta.GenerativeQuestionServiceClient() + + # Initialize request argument(s) + generative_questions_feature_config = retail_v2beta.GenerativeQuestionsFeatureConfig() + generative_questions_feature_config.catalog = "catalog_value" + + request = retail_v2beta.UpdateGenerativeQuestionsFeatureConfigRequest( + generative_questions_feature_config=generative_questions_feature_config, + ) + + # Make the request + response = client.update_generative_questions_feature_config(request=request) + + # Handle the response + print(response) + +# [END retail_v2beta_generated_GenerativeQuestionService_UpdateGenerativeQuestionsFeatureConfig_sync] diff --git a/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_product_service_export_products_async.py b/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_product_service_export_products_async.py new file mode 100644 index 000000000000..b7253ba95a33 --- /dev/null +++ b/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_product_service_export_products_async.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for ExportProducts +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-retail + + +# [START retail_v2beta_generated_ProductService_ExportProducts_async] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import retail_v2beta + + +async def sample_export_products(): + # Create a client + client = retail_v2beta.ProductServiceAsyncClient() + + # Initialize request argument(s) + output_config = retail_v2beta.OutputConfig() + output_config.gcs_destination.output_uri_prefix = "output_uri_prefix_value" + + request = retail_v2beta.ExportProductsRequest( + parent="parent_value", + output_config=output_config, + ) + + # Make the request + operation = client.export_products(request=request) + + print("Waiting for operation to complete...") + + response = (await operation).result() + + # Handle the response + print(response) + +# [END retail_v2beta_generated_ProductService_ExportProducts_async] diff --git a/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_product_service_export_products_sync.py b/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_product_service_export_products_sync.py new file mode 100644 index 000000000000..a8fea6d48d33 --- /dev/null +++ b/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_product_service_export_products_sync.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for ExportProducts +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-retail + + +# [START retail_v2beta_generated_ProductService_ExportProducts_sync] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import retail_v2beta + + +def sample_export_products(): + # Create a client + client = retail_v2beta.ProductServiceClient() + + # Initialize request argument(s) + output_config = retail_v2beta.OutputConfig() + output_config.gcs_destination.output_uri_prefix = "output_uri_prefix_value" + + request = retail_v2beta.ExportProductsRequest( + parent="parent_value", + output_config=output_config, + ) + + # Make the request + operation = client.export_products(request=request) + + print("Waiting for operation to complete...") + + response = operation.result() + + # Handle the response + print(response) + +# [END retail_v2beta_generated_ProductService_ExportProducts_sync] diff --git a/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_project_service_get_alert_config_async.py b/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_project_service_get_alert_config_async.py new file mode 100644 index 000000000000..598c5396f13f --- /dev/null +++ b/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_project_service_get_alert_config_async.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for GetAlertConfig +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-retail + + +# [START retail_v2beta_generated_ProjectService_GetAlertConfig_async] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import retail_v2beta + + +async def sample_get_alert_config(): + # Create a client + client = retail_v2beta.ProjectServiceAsyncClient() + + # Initialize request argument(s) + request = retail_v2beta.GetAlertConfigRequest( + name="name_value", + ) + + # Make the request + response = await client.get_alert_config(request=request) + + # Handle the response + print(response) + +# [END retail_v2beta_generated_ProjectService_GetAlertConfig_async] diff --git a/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_project_service_get_alert_config_sync.py b/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_project_service_get_alert_config_sync.py new file mode 100644 index 000000000000..ebc23688e8b0 --- /dev/null +++ b/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_project_service_get_alert_config_sync.py @@ -0,0 +1,52 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for GetAlertConfig +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-retail + + +# [START retail_v2beta_generated_ProjectService_GetAlertConfig_sync] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import retail_v2beta + + +def sample_get_alert_config(): + # Create a client + client = retail_v2beta.ProjectServiceClient() + + # Initialize request argument(s) + request = retail_v2beta.GetAlertConfigRequest( + name="name_value", + ) + + # Make the request + response = client.get_alert_config(request=request) + + # Handle the response + print(response) + +# [END retail_v2beta_generated_ProjectService_GetAlertConfig_sync] diff --git a/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_project_service_update_alert_config_async.py b/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_project_service_update_alert_config_async.py new file mode 100644 index 000000000000..b91f582a385d --- /dev/null +++ b/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_project_service_update_alert_config_async.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for UpdateAlertConfig +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-retail + + +# [START retail_v2beta_generated_ProjectService_UpdateAlertConfig_async] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import retail_v2beta + + +async def sample_update_alert_config(): + # Create a client + client = retail_v2beta.ProjectServiceAsyncClient() + + # Initialize request argument(s) + alert_config = retail_v2beta.AlertConfig() + alert_config.name = "name_value" + + request = retail_v2beta.UpdateAlertConfigRequest( + alert_config=alert_config, + ) + + # Make the request + response = await client.update_alert_config(request=request) + + # Handle the response + print(response) + +# [END retail_v2beta_generated_ProjectService_UpdateAlertConfig_async] diff --git a/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_project_service_update_alert_config_sync.py b/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_project_service_update_alert_config_sync.py new file mode 100644 index 000000000000..8465f5c459fe --- /dev/null +++ b/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_project_service_update_alert_config_sync.py @@ -0,0 +1,55 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for UpdateAlertConfig +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-retail + + +# [START retail_v2beta_generated_ProjectService_UpdateAlertConfig_sync] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import retail_v2beta + + +def sample_update_alert_config(): + # Create a client + client = retail_v2beta.ProjectServiceClient() + + # Initialize request argument(s) + alert_config = retail_v2beta.AlertConfig() + alert_config.name = "name_value" + + request = retail_v2beta.UpdateAlertConfigRequest( + alert_config=alert_config, + ) + + # Make the request + response = client.update_alert_config(request=request) + + # Handle the response + print(response) + +# [END retail_v2beta_generated_ProjectService_UpdateAlertConfig_sync] diff --git a/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_user_event_service_export_user_events_async.py b/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_user_event_service_export_user_events_async.py new file mode 100644 index 000000000000..da5f63aa2d21 --- /dev/null +++ b/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_user_event_service_export_user_events_async.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for ExportUserEvents +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-retail + + +# [START retail_v2beta_generated_UserEventService_ExportUserEvents_async] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import retail_v2beta + + +async def sample_export_user_events(): + # Create a client + client = retail_v2beta.UserEventServiceAsyncClient() + + # Initialize request argument(s) + output_config = retail_v2beta.OutputConfig() + output_config.gcs_destination.output_uri_prefix = "output_uri_prefix_value" + + request = retail_v2beta.ExportUserEventsRequest( + parent="parent_value", + output_config=output_config, + ) + + # Make the request + operation = client.export_user_events(request=request) + + print("Waiting for operation to complete...") + + response = (await operation).result() + + # Handle the response + print(response) + +# [END retail_v2beta_generated_UserEventService_ExportUserEvents_async] diff --git a/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_user_event_service_export_user_events_sync.py b/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_user_event_service_export_user_events_sync.py new file mode 100644 index 000000000000..79c4f6353420 --- /dev/null +++ b/packages/google-cloud-retail/samples/generated_samples/retail_v2beta_generated_user_event_service_export_user_events_sync.py @@ -0,0 +1,60 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# Generated code. DO NOT EDIT! +# +# Snippet for ExportUserEvents +# NOTE: This snippet has been automatically generated for illustrative purposes only. +# It may require modifications to work in your environment. + +# To install the latest published package dependency, execute the following: +# python3 -m pip install google-cloud-retail + + +# [START retail_v2beta_generated_UserEventService_ExportUserEvents_sync] +# This snippet has been automatically generated and should be regarded as a +# code template only. +# It will require modifications to work: +# - It may require correct/in-range values for request initialization. +# - It may require specifying regional endpoints when creating the service +# client as shown in: +# https://googleapis.dev/python/google-api-core/latest/client_options.html +from google.cloud import retail_v2beta + + +def sample_export_user_events(): + # Create a client + client = retail_v2beta.UserEventServiceClient() + + # Initialize request argument(s) + output_config = retail_v2beta.OutputConfig() + output_config.gcs_destination.output_uri_prefix = "output_uri_prefix_value" + + request = retail_v2beta.ExportUserEventsRequest( + parent="parent_value", + output_config=output_config, + ) + + # Make the request + operation = client.export_user_events(request=request) + + print("Waiting for operation to complete...") + + response = operation.result() + + # Handle the response + print(response) + +# [END retail_v2beta_generated_UserEventService_ExportUserEvents_sync] diff --git a/packages/google-cloud-retail/samples/generated_samples/snippet_metadata_google.cloud.retail.v2.json b/packages/google-cloud-retail/samples/generated_samples/snippet_metadata_google.cloud.retail.v2.json index 2660f295abc7..bd7fbc1b355a 100644 --- a/packages/google-cloud-retail/samples/generated_samples/snippet_metadata_google.cloud.retail.v2.json +++ b/packages/google-cloud-retail/samples/generated_samples/snippet_metadata_google.cloud.retail.v2.json @@ -3058,6 +3058,835 @@ ], "title": "retail_v2_generated_control_service_update_control_sync.py" }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.retail_v2.GenerativeQuestionServiceAsyncClient", + "shortName": "GenerativeQuestionServiceAsyncClient" + }, + "fullName": "google.cloud.retail_v2.GenerativeQuestionServiceAsyncClient.batch_update_generative_question_configs", + "method": { + "fullName": "google.cloud.retail.v2.GenerativeQuestionService.BatchUpdateGenerativeQuestionConfigs", + "service": { + "fullName": "google.cloud.retail.v2.GenerativeQuestionService", + "shortName": "GenerativeQuestionService" + }, + "shortName": "BatchUpdateGenerativeQuestionConfigs" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.retail_v2.types.BatchUpdateGenerativeQuestionConfigsRequest" + }, + { + "name": "parent", + "type": "str" + }, + { + "name": "requests", + "type": "MutableSequence[google.cloud.retail_v2.types.UpdateGenerativeQuestionConfigRequest]" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.cloud.retail_v2.types.BatchUpdateGenerativeQuestionConfigsResponse", + "shortName": "batch_update_generative_question_configs" + }, + "description": "Sample for BatchUpdateGenerativeQuestionConfigs", + "file": "retail_v2_generated_generative_question_service_batch_update_generative_question_configs_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "retail_v2_generated_GenerativeQuestionService_BatchUpdateGenerativeQuestionConfigs_async", + "segments": [ + { + "end": 55, + "start": 27, + "type": "FULL" + }, + { + "end": 55, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 49, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 52, + "start": 50, + "type": "REQUEST_EXECUTION" + }, + { + "end": 56, + "start": 53, + "type": "RESPONSE_HANDLING" + } + ], + "title": "retail_v2_generated_generative_question_service_batch_update_generative_question_configs_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.retail_v2.GenerativeQuestionServiceClient", + "shortName": "GenerativeQuestionServiceClient" + }, + "fullName": "google.cloud.retail_v2.GenerativeQuestionServiceClient.batch_update_generative_question_configs", + "method": { + "fullName": "google.cloud.retail.v2.GenerativeQuestionService.BatchUpdateGenerativeQuestionConfigs", + "service": { + "fullName": "google.cloud.retail.v2.GenerativeQuestionService", + "shortName": "GenerativeQuestionService" + }, + "shortName": "BatchUpdateGenerativeQuestionConfigs" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.retail_v2.types.BatchUpdateGenerativeQuestionConfigsRequest" + }, + { + "name": "parent", + "type": "str" + }, + { + "name": "requests", + "type": "MutableSequence[google.cloud.retail_v2.types.UpdateGenerativeQuestionConfigRequest]" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.cloud.retail_v2.types.BatchUpdateGenerativeQuestionConfigsResponse", + "shortName": "batch_update_generative_question_configs" + }, + "description": "Sample for BatchUpdateGenerativeQuestionConfigs", + "file": "retail_v2_generated_generative_question_service_batch_update_generative_question_configs_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "retail_v2_generated_GenerativeQuestionService_BatchUpdateGenerativeQuestionConfigs_sync", + "segments": [ + { + "end": 55, + "start": 27, + "type": "FULL" + }, + { + "end": 55, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 49, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 52, + "start": 50, + "type": "REQUEST_EXECUTION" + }, + { + "end": 56, + "start": 53, + "type": "RESPONSE_HANDLING" + } + ], + "title": "retail_v2_generated_generative_question_service_batch_update_generative_question_configs_sync.py" + }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.retail_v2.GenerativeQuestionServiceAsyncClient", + "shortName": "GenerativeQuestionServiceAsyncClient" + }, + "fullName": "google.cloud.retail_v2.GenerativeQuestionServiceAsyncClient.get_generative_questions_feature_config", + "method": { + "fullName": "google.cloud.retail.v2.GenerativeQuestionService.GetGenerativeQuestionsFeatureConfig", + "service": { + "fullName": "google.cloud.retail.v2.GenerativeQuestionService", + "shortName": "GenerativeQuestionService" + }, + "shortName": "GetGenerativeQuestionsFeatureConfig" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.retail_v2.types.GetGenerativeQuestionsFeatureConfigRequest" + }, + { + "name": "catalog", + "type": "str" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.cloud.retail_v2.types.GenerativeQuestionsFeatureConfig", + "shortName": "get_generative_questions_feature_config" + }, + "description": "Sample for GetGenerativeQuestionsFeatureConfig", + "file": "retail_v2_generated_generative_question_service_get_generative_questions_feature_config_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "retail_v2_generated_GenerativeQuestionService_GetGenerativeQuestionsFeatureConfig_async", + "segments": [ + { + "end": 51, + "start": 27, + "type": "FULL" + }, + { + "end": 51, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 45, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 48, + "start": 46, + "type": "REQUEST_EXECUTION" + }, + { + "end": 52, + "start": 49, + "type": "RESPONSE_HANDLING" + } + ], + "title": "retail_v2_generated_generative_question_service_get_generative_questions_feature_config_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.retail_v2.GenerativeQuestionServiceClient", + "shortName": "GenerativeQuestionServiceClient" + }, + "fullName": "google.cloud.retail_v2.GenerativeQuestionServiceClient.get_generative_questions_feature_config", + "method": { + "fullName": "google.cloud.retail.v2.GenerativeQuestionService.GetGenerativeQuestionsFeatureConfig", + "service": { + "fullName": "google.cloud.retail.v2.GenerativeQuestionService", + "shortName": "GenerativeQuestionService" + }, + "shortName": "GetGenerativeQuestionsFeatureConfig" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.retail_v2.types.GetGenerativeQuestionsFeatureConfigRequest" + }, + { + "name": "catalog", + "type": "str" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.cloud.retail_v2.types.GenerativeQuestionsFeatureConfig", + "shortName": "get_generative_questions_feature_config" + }, + "description": "Sample for GetGenerativeQuestionsFeatureConfig", + "file": "retail_v2_generated_generative_question_service_get_generative_questions_feature_config_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "retail_v2_generated_GenerativeQuestionService_GetGenerativeQuestionsFeatureConfig_sync", + "segments": [ + { + "end": 51, + "start": 27, + "type": "FULL" + }, + { + "end": 51, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 45, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 48, + "start": 46, + "type": "REQUEST_EXECUTION" + }, + { + "end": 52, + "start": 49, + "type": "RESPONSE_HANDLING" + } + ], + "title": "retail_v2_generated_generative_question_service_get_generative_questions_feature_config_sync.py" + }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.retail_v2.GenerativeQuestionServiceAsyncClient", + "shortName": "GenerativeQuestionServiceAsyncClient" + }, + "fullName": "google.cloud.retail_v2.GenerativeQuestionServiceAsyncClient.list_generative_question_configs", + "method": { + "fullName": "google.cloud.retail.v2.GenerativeQuestionService.ListGenerativeQuestionConfigs", + "service": { + "fullName": "google.cloud.retail.v2.GenerativeQuestionService", + "shortName": "GenerativeQuestionService" + }, + "shortName": "ListGenerativeQuestionConfigs" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.retail_v2.types.ListGenerativeQuestionConfigsRequest" + }, + { + "name": "parent", + "type": "str" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.cloud.retail_v2.types.ListGenerativeQuestionConfigsResponse", + "shortName": "list_generative_question_configs" + }, + "description": "Sample for ListGenerativeQuestionConfigs", + "file": "retail_v2_generated_generative_question_service_list_generative_question_configs_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "retail_v2_generated_GenerativeQuestionService_ListGenerativeQuestionConfigs_async", + "segments": [ + { + "end": 51, + "start": 27, + "type": "FULL" + }, + { + "end": 51, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 45, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 48, + "start": 46, + "type": "REQUEST_EXECUTION" + }, + { + "end": 52, + "start": 49, + "type": "RESPONSE_HANDLING" + } + ], + "title": "retail_v2_generated_generative_question_service_list_generative_question_configs_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.retail_v2.GenerativeQuestionServiceClient", + "shortName": "GenerativeQuestionServiceClient" + }, + "fullName": "google.cloud.retail_v2.GenerativeQuestionServiceClient.list_generative_question_configs", + "method": { + "fullName": "google.cloud.retail.v2.GenerativeQuestionService.ListGenerativeQuestionConfigs", + "service": { + "fullName": "google.cloud.retail.v2.GenerativeQuestionService", + "shortName": "GenerativeQuestionService" + }, + "shortName": "ListGenerativeQuestionConfigs" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.retail_v2.types.ListGenerativeQuestionConfigsRequest" + }, + { + "name": "parent", + "type": "str" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.cloud.retail_v2.types.ListGenerativeQuestionConfigsResponse", + "shortName": "list_generative_question_configs" + }, + "description": "Sample for ListGenerativeQuestionConfigs", + "file": "retail_v2_generated_generative_question_service_list_generative_question_configs_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "retail_v2_generated_GenerativeQuestionService_ListGenerativeQuestionConfigs_sync", + "segments": [ + { + "end": 51, + "start": 27, + "type": "FULL" + }, + { + "end": 51, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 45, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 48, + "start": 46, + "type": "REQUEST_EXECUTION" + }, + { + "end": 52, + "start": 49, + "type": "RESPONSE_HANDLING" + } + ], + "title": "retail_v2_generated_generative_question_service_list_generative_question_configs_sync.py" + }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.retail_v2.GenerativeQuestionServiceAsyncClient", + "shortName": "GenerativeQuestionServiceAsyncClient" + }, + "fullName": "google.cloud.retail_v2.GenerativeQuestionServiceAsyncClient.update_generative_question_config", + "method": { + "fullName": "google.cloud.retail.v2.GenerativeQuestionService.UpdateGenerativeQuestionConfig", + "service": { + "fullName": "google.cloud.retail.v2.GenerativeQuestionService", + "shortName": "GenerativeQuestionService" + }, + "shortName": "UpdateGenerativeQuestionConfig" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.retail_v2.types.UpdateGenerativeQuestionConfigRequest" + }, + { + "name": "generative_question_config", + "type": "google.cloud.retail_v2.types.GenerativeQuestionConfig" + }, + { + "name": "update_mask", + "type": "google.protobuf.field_mask_pb2.FieldMask" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.cloud.retail_v2.types.GenerativeQuestionConfig", + "shortName": "update_generative_question_config" + }, + "description": "Sample for UpdateGenerativeQuestionConfig", + "file": "retail_v2_generated_generative_question_service_update_generative_question_config_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "retail_v2_generated_GenerativeQuestionService_UpdateGenerativeQuestionConfig_async", + "segments": [ + { + "end": 55, + "start": 27, + "type": "FULL" + }, + { + "end": 55, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 49, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 52, + "start": 50, + "type": "REQUEST_EXECUTION" + }, + { + "end": 56, + "start": 53, + "type": "RESPONSE_HANDLING" + } + ], + "title": "retail_v2_generated_generative_question_service_update_generative_question_config_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.retail_v2.GenerativeQuestionServiceClient", + "shortName": "GenerativeQuestionServiceClient" + }, + "fullName": "google.cloud.retail_v2.GenerativeQuestionServiceClient.update_generative_question_config", + "method": { + "fullName": "google.cloud.retail.v2.GenerativeQuestionService.UpdateGenerativeQuestionConfig", + "service": { + "fullName": "google.cloud.retail.v2.GenerativeQuestionService", + "shortName": "GenerativeQuestionService" + }, + "shortName": "UpdateGenerativeQuestionConfig" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.retail_v2.types.UpdateGenerativeQuestionConfigRequest" + }, + { + "name": "generative_question_config", + "type": "google.cloud.retail_v2.types.GenerativeQuestionConfig" + }, + { + "name": "update_mask", + "type": "google.protobuf.field_mask_pb2.FieldMask" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.cloud.retail_v2.types.GenerativeQuestionConfig", + "shortName": "update_generative_question_config" + }, + "description": "Sample for UpdateGenerativeQuestionConfig", + "file": "retail_v2_generated_generative_question_service_update_generative_question_config_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "retail_v2_generated_GenerativeQuestionService_UpdateGenerativeQuestionConfig_sync", + "segments": [ + { + "end": 55, + "start": 27, + "type": "FULL" + }, + { + "end": 55, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 49, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 52, + "start": 50, + "type": "REQUEST_EXECUTION" + }, + { + "end": 56, + "start": 53, + "type": "RESPONSE_HANDLING" + } + ], + "title": "retail_v2_generated_generative_question_service_update_generative_question_config_sync.py" + }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.retail_v2.GenerativeQuestionServiceAsyncClient", + "shortName": "GenerativeQuestionServiceAsyncClient" + }, + "fullName": "google.cloud.retail_v2.GenerativeQuestionServiceAsyncClient.update_generative_questions_feature_config", + "method": { + "fullName": "google.cloud.retail.v2.GenerativeQuestionService.UpdateGenerativeQuestionsFeatureConfig", + "service": { + "fullName": "google.cloud.retail.v2.GenerativeQuestionService", + "shortName": "GenerativeQuestionService" + }, + "shortName": "UpdateGenerativeQuestionsFeatureConfig" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.retail_v2.types.UpdateGenerativeQuestionsFeatureConfigRequest" + }, + { + "name": "generative_questions_feature_config", + "type": "google.cloud.retail_v2.types.GenerativeQuestionsFeatureConfig" + }, + { + "name": "update_mask", + "type": "google.protobuf.field_mask_pb2.FieldMask" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.cloud.retail_v2.types.GenerativeQuestionsFeatureConfig", + "shortName": "update_generative_questions_feature_config" + }, + "description": "Sample for UpdateGenerativeQuestionsFeatureConfig", + "file": "retail_v2_generated_generative_question_service_update_generative_questions_feature_config_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "retail_v2_generated_GenerativeQuestionService_UpdateGenerativeQuestionsFeatureConfig_async", + "segments": [ + { + "end": 54, + "start": 27, + "type": "FULL" + }, + { + "end": 54, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 48, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 51, + "start": 49, + "type": "REQUEST_EXECUTION" + }, + { + "end": 55, + "start": 52, + "type": "RESPONSE_HANDLING" + } + ], + "title": "retail_v2_generated_generative_question_service_update_generative_questions_feature_config_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.retail_v2.GenerativeQuestionServiceClient", + "shortName": "GenerativeQuestionServiceClient" + }, + "fullName": "google.cloud.retail_v2.GenerativeQuestionServiceClient.update_generative_questions_feature_config", + "method": { + "fullName": "google.cloud.retail.v2.GenerativeQuestionService.UpdateGenerativeQuestionsFeatureConfig", + "service": { + "fullName": "google.cloud.retail.v2.GenerativeQuestionService", + "shortName": "GenerativeQuestionService" + }, + "shortName": "UpdateGenerativeQuestionsFeatureConfig" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.retail_v2.types.UpdateGenerativeQuestionsFeatureConfigRequest" + }, + { + "name": "generative_questions_feature_config", + "type": "google.cloud.retail_v2.types.GenerativeQuestionsFeatureConfig" + }, + { + "name": "update_mask", + "type": "google.protobuf.field_mask_pb2.FieldMask" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.cloud.retail_v2.types.GenerativeQuestionsFeatureConfig", + "shortName": "update_generative_questions_feature_config" + }, + "description": "Sample for UpdateGenerativeQuestionsFeatureConfig", + "file": "retail_v2_generated_generative_question_service_update_generative_questions_feature_config_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "retail_v2_generated_GenerativeQuestionService_UpdateGenerativeQuestionsFeatureConfig_sync", + "segments": [ + { + "end": 54, + "start": 27, + "type": "FULL" + }, + { + "end": 54, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 48, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 51, + "start": 49, + "type": "REQUEST_EXECUTION" + }, + { + "end": 55, + "start": 52, + "type": "RESPONSE_HANDLING" + } + ], + "title": "retail_v2_generated_generative_question_service_update_generative_questions_feature_config_sync.py" + }, { "canonical": true, "clientMethod": { diff --git a/packages/google-cloud-retail/samples/generated_samples/snippet_metadata_google.cloud.retail.v2alpha.json b/packages/google-cloud-retail/samples/generated_samples/snippet_metadata_google.cloud.retail.v2alpha.json index 0005b981abd9..2bad2703cfbd 100644 --- a/packages/google-cloud-retail/samples/generated_samples/snippet_metadata_google.cloud.retail.v2alpha.json +++ b/packages/google-cloud-retail/samples/generated_samples/snippet_metadata_google.cloud.retail.v2alpha.json @@ -3533,6 +3533,835 @@ ], "title": "retail_v2alpha_generated_control_service_update_control_sync.py" }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.retail_v2alpha.GenerativeQuestionServiceAsyncClient", + "shortName": "GenerativeQuestionServiceAsyncClient" + }, + "fullName": "google.cloud.retail_v2alpha.GenerativeQuestionServiceAsyncClient.batch_update_generative_question_configs", + "method": { + "fullName": "google.cloud.retail.v2alpha.GenerativeQuestionService.BatchUpdateGenerativeQuestionConfigs", + "service": { + "fullName": "google.cloud.retail.v2alpha.GenerativeQuestionService", + "shortName": "GenerativeQuestionService" + }, + "shortName": "BatchUpdateGenerativeQuestionConfigs" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.retail_v2alpha.types.BatchUpdateGenerativeQuestionConfigsRequest" + }, + { + "name": "parent", + "type": "str" + }, + { + "name": "requests", + "type": "MutableSequence[google.cloud.retail_v2alpha.types.UpdateGenerativeQuestionConfigRequest]" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.cloud.retail_v2alpha.types.BatchUpdateGenerativeQuestionConfigsResponse", + "shortName": "batch_update_generative_question_configs" + }, + "description": "Sample for BatchUpdateGenerativeQuestionConfigs", + "file": "retail_v2alpha_generated_generative_question_service_batch_update_generative_question_configs_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "retail_v2alpha_generated_GenerativeQuestionService_BatchUpdateGenerativeQuestionConfigs_async", + "segments": [ + { + "end": 55, + "start": 27, + "type": "FULL" + }, + { + "end": 55, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 49, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 52, + "start": 50, + "type": "REQUEST_EXECUTION" + }, + { + "end": 56, + "start": 53, + "type": "RESPONSE_HANDLING" + } + ], + "title": "retail_v2alpha_generated_generative_question_service_batch_update_generative_question_configs_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.retail_v2alpha.GenerativeQuestionServiceClient", + "shortName": "GenerativeQuestionServiceClient" + }, + "fullName": "google.cloud.retail_v2alpha.GenerativeQuestionServiceClient.batch_update_generative_question_configs", + "method": { + "fullName": "google.cloud.retail.v2alpha.GenerativeQuestionService.BatchUpdateGenerativeQuestionConfigs", + "service": { + "fullName": "google.cloud.retail.v2alpha.GenerativeQuestionService", + "shortName": "GenerativeQuestionService" + }, + "shortName": "BatchUpdateGenerativeQuestionConfigs" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.retail_v2alpha.types.BatchUpdateGenerativeQuestionConfigsRequest" + }, + { + "name": "parent", + "type": "str" + }, + { + "name": "requests", + "type": "MutableSequence[google.cloud.retail_v2alpha.types.UpdateGenerativeQuestionConfigRequest]" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.cloud.retail_v2alpha.types.BatchUpdateGenerativeQuestionConfigsResponse", + "shortName": "batch_update_generative_question_configs" + }, + "description": "Sample for BatchUpdateGenerativeQuestionConfigs", + "file": "retail_v2alpha_generated_generative_question_service_batch_update_generative_question_configs_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "retail_v2alpha_generated_GenerativeQuestionService_BatchUpdateGenerativeQuestionConfigs_sync", + "segments": [ + { + "end": 55, + "start": 27, + "type": "FULL" + }, + { + "end": 55, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 49, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 52, + "start": 50, + "type": "REQUEST_EXECUTION" + }, + { + "end": 56, + "start": 53, + "type": "RESPONSE_HANDLING" + } + ], + "title": "retail_v2alpha_generated_generative_question_service_batch_update_generative_question_configs_sync.py" + }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.retail_v2alpha.GenerativeQuestionServiceAsyncClient", + "shortName": "GenerativeQuestionServiceAsyncClient" + }, + "fullName": "google.cloud.retail_v2alpha.GenerativeQuestionServiceAsyncClient.get_generative_questions_feature_config", + "method": { + "fullName": "google.cloud.retail.v2alpha.GenerativeQuestionService.GetGenerativeQuestionsFeatureConfig", + "service": { + "fullName": "google.cloud.retail.v2alpha.GenerativeQuestionService", + "shortName": "GenerativeQuestionService" + }, + "shortName": "GetGenerativeQuestionsFeatureConfig" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.retail_v2alpha.types.GetGenerativeQuestionsFeatureConfigRequest" + }, + { + "name": "catalog", + "type": "str" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.cloud.retail_v2alpha.types.GenerativeQuestionsFeatureConfig", + "shortName": "get_generative_questions_feature_config" + }, + "description": "Sample for GetGenerativeQuestionsFeatureConfig", + "file": "retail_v2alpha_generated_generative_question_service_get_generative_questions_feature_config_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "retail_v2alpha_generated_GenerativeQuestionService_GetGenerativeQuestionsFeatureConfig_async", + "segments": [ + { + "end": 51, + "start": 27, + "type": "FULL" + }, + { + "end": 51, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 45, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 48, + "start": 46, + "type": "REQUEST_EXECUTION" + }, + { + "end": 52, + "start": 49, + "type": "RESPONSE_HANDLING" + } + ], + "title": "retail_v2alpha_generated_generative_question_service_get_generative_questions_feature_config_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.retail_v2alpha.GenerativeQuestionServiceClient", + "shortName": "GenerativeQuestionServiceClient" + }, + "fullName": "google.cloud.retail_v2alpha.GenerativeQuestionServiceClient.get_generative_questions_feature_config", + "method": { + "fullName": "google.cloud.retail.v2alpha.GenerativeQuestionService.GetGenerativeQuestionsFeatureConfig", + "service": { + "fullName": "google.cloud.retail.v2alpha.GenerativeQuestionService", + "shortName": "GenerativeQuestionService" + }, + "shortName": "GetGenerativeQuestionsFeatureConfig" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.retail_v2alpha.types.GetGenerativeQuestionsFeatureConfigRequest" + }, + { + "name": "catalog", + "type": "str" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.cloud.retail_v2alpha.types.GenerativeQuestionsFeatureConfig", + "shortName": "get_generative_questions_feature_config" + }, + "description": "Sample for GetGenerativeQuestionsFeatureConfig", + "file": "retail_v2alpha_generated_generative_question_service_get_generative_questions_feature_config_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "retail_v2alpha_generated_GenerativeQuestionService_GetGenerativeQuestionsFeatureConfig_sync", + "segments": [ + { + "end": 51, + "start": 27, + "type": "FULL" + }, + { + "end": 51, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 45, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 48, + "start": 46, + "type": "REQUEST_EXECUTION" + }, + { + "end": 52, + "start": 49, + "type": "RESPONSE_HANDLING" + } + ], + "title": "retail_v2alpha_generated_generative_question_service_get_generative_questions_feature_config_sync.py" + }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.retail_v2alpha.GenerativeQuestionServiceAsyncClient", + "shortName": "GenerativeQuestionServiceAsyncClient" + }, + "fullName": "google.cloud.retail_v2alpha.GenerativeQuestionServiceAsyncClient.list_generative_question_configs", + "method": { + "fullName": "google.cloud.retail.v2alpha.GenerativeQuestionService.ListGenerativeQuestionConfigs", + "service": { + "fullName": "google.cloud.retail.v2alpha.GenerativeQuestionService", + "shortName": "GenerativeQuestionService" + }, + "shortName": "ListGenerativeQuestionConfigs" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.retail_v2alpha.types.ListGenerativeQuestionConfigsRequest" + }, + { + "name": "parent", + "type": "str" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.cloud.retail_v2alpha.types.ListGenerativeQuestionConfigsResponse", + "shortName": "list_generative_question_configs" + }, + "description": "Sample for ListGenerativeQuestionConfigs", + "file": "retail_v2alpha_generated_generative_question_service_list_generative_question_configs_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "retail_v2alpha_generated_GenerativeQuestionService_ListGenerativeQuestionConfigs_async", + "segments": [ + { + "end": 51, + "start": 27, + "type": "FULL" + }, + { + "end": 51, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 45, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 48, + "start": 46, + "type": "REQUEST_EXECUTION" + }, + { + "end": 52, + "start": 49, + "type": "RESPONSE_HANDLING" + } + ], + "title": "retail_v2alpha_generated_generative_question_service_list_generative_question_configs_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.retail_v2alpha.GenerativeQuestionServiceClient", + "shortName": "GenerativeQuestionServiceClient" + }, + "fullName": "google.cloud.retail_v2alpha.GenerativeQuestionServiceClient.list_generative_question_configs", + "method": { + "fullName": "google.cloud.retail.v2alpha.GenerativeQuestionService.ListGenerativeQuestionConfigs", + "service": { + "fullName": "google.cloud.retail.v2alpha.GenerativeQuestionService", + "shortName": "GenerativeQuestionService" + }, + "shortName": "ListGenerativeQuestionConfigs" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.retail_v2alpha.types.ListGenerativeQuestionConfigsRequest" + }, + { + "name": "parent", + "type": "str" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.cloud.retail_v2alpha.types.ListGenerativeQuestionConfigsResponse", + "shortName": "list_generative_question_configs" + }, + "description": "Sample for ListGenerativeQuestionConfigs", + "file": "retail_v2alpha_generated_generative_question_service_list_generative_question_configs_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "retail_v2alpha_generated_GenerativeQuestionService_ListGenerativeQuestionConfigs_sync", + "segments": [ + { + "end": 51, + "start": 27, + "type": "FULL" + }, + { + "end": 51, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 45, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 48, + "start": 46, + "type": "REQUEST_EXECUTION" + }, + { + "end": 52, + "start": 49, + "type": "RESPONSE_HANDLING" + } + ], + "title": "retail_v2alpha_generated_generative_question_service_list_generative_question_configs_sync.py" + }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.retail_v2alpha.GenerativeQuestionServiceAsyncClient", + "shortName": "GenerativeQuestionServiceAsyncClient" + }, + "fullName": "google.cloud.retail_v2alpha.GenerativeQuestionServiceAsyncClient.update_generative_question_config", + "method": { + "fullName": "google.cloud.retail.v2alpha.GenerativeQuestionService.UpdateGenerativeQuestionConfig", + "service": { + "fullName": "google.cloud.retail.v2alpha.GenerativeQuestionService", + "shortName": "GenerativeQuestionService" + }, + "shortName": "UpdateGenerativeQuestionConfig" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.retail_v2alpha.types.UpdateGenerativeQuestionConfigRequest" + }, + { + "name": "generative_question_config", + "type": "google.cloud.retail_v2alpha.types.GenerativeQuestionConfig" + }, + { + "name": "update_mask", + "type": "google.protobuf.field_mask_pb2.FieldMask" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.cloud.retail_v2alpha.types.GenerativeQuestionConfig", + "shortName": "update_generative_question_config" + }, + "description": "Sample for UpdateGenerativeQuestionConfig", + "file": "retail_v2alpha_generated_generative_question_service_update_generative_question_config_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "retail_v2alpha_generated_GenerativeQuestionService_UpdateGenerativeQuestionConfig_async", + "segments": [ + { + "end": 55, + "start": 27, + "type": "FULL" + }, + { + "end": 55, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 49, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 52, + "start": 50, + "type": "REQUEST_EXECUTION" + }, + { + "end": 56, + "start": 53, + "type": "RESPONSE_HANDLING" + } + ], + "title": "retail_v2alpha_generated_generative_question_service_update_generative_question_config_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.retail_v2alpha.GenerativeQuestionServiceClient", + "shortName": "GenerativeQuestionServiceClient" + }, + "fullName": "google.cloud.retail_v2alpha.GenerativeQuestionServiceClient.update_generative_question_config", + "method": { + "fullName": "google.cloud.retail.v2alpha.GenerativeQuestionService.UpdateGenerativeQuestionConfig", + "service": { + "fullName": "google.cloud.retail.v2alpha.GenerativeQuestionService", + "shortName": "GenerativeQuestionService" + }, + "shortName": "UpdateGenerativeQuestionConfig" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.retail_v2alpha.types.UpdateGenerativeQuestionConfigRequest" + }, + { + "name": "generative_question_config", + "type": "google.cloud.retail_v2alpha.types.GenerativeQuestionConfig" + }, + { + "name": "update_mask", + "type": "google.protobuf.field_mask_pb2.FieldMask" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.cloud.retail_v2alpha.types.GenerativeQuestionConfig", + "shortName": "update_generative_question_config" + }, + "description": "Sample for UpdateGenerativeQuestionConfig", + "file": "retail_v2alpha_generated_generative_question_service_update_generative_question_config_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "retail_v2alpha_generated_GenerativeQuestionService_UpdateGenerativeQuestionConfig_sync", + "segments": [ + { + "end": 55, + "start": 27, + "type": "FULL" + }, + { + "end": 55, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 49, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 52, + "start": 50, + "type": "REQUEST_EXECUTION" + }, + { + "end": 56, + "start": 53, + "type": "RESPONSE_HANDLING" + } + ], + "title": "retail_v2alpha_generated_generative_question_service_update_generative_question_config_sync.py" + }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.retail_v2alpha.GenerativeQuestionServiceAsyncClient", + "shortName": "GenerativeQuestionServiceAsyncClient" + }, + "fullName": "google.cloud.retail_v2alpha.GenerativeQuestionServiceAsyncClient.update_generative_questions_feature_config", + "method": { + "fullName": "google.cloud.retail.v2alpha.GenerativeQuestionService.UpdateGenerativeQuestionsFeatureConfig", + "service": { + "fullName": "google.cloud.retail.v2alpha.GenerativeQuestionService", + "shortName": "GenerativeQuestionService" + }, + "shortName": "UpdateGenerativeQuestionsFeatureConfig" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.retail_v2alpha.types.UpdateGenerativeQuestionsFeatureConfigRequest" + }, + { + "name": "generative_questions_feature_config", + "type": "google.cloud.retail_v2alpha.types.GenerativeQuestionsFeatureConfig" + }, + { + "name": "update_mask", + "type": "google.protobuf.field_mask_pb2.FieldMask" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.cloud.retail_v2alpha.types.GenerativeQuestionsFeatureConfig", + "shortName": "update_generative_questions_feature_config" + }, + "description": "Sample for UpdateGenerativeQuestionsFeatureConfig", + "file": "retail_v2alpha_generated_generative_question_service_update_generative_questions_feature_config_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "retail_v2alpha_generated_GenerativeQuestionService_UpdateGenerativeQuestionsFeatureConfig_async", + "segments": [ + { + "end": 54, + "start": 27, + "type": "FULL" + }, + { + "end": 54, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 48, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 51, + "start": 49, + "type": "REQUEST_EXECUTION" + }, + { + "end": 55, + "start": 52, + "type": "RESPONSE_HANDLING" + } + ], + "title": "retail_v2alpha_generated_generative_question_service_update_generative_questions_feature_config_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.retail_v2alpha.GenerativeQuestionServiceClient", + "shortName": "GenerativeQuestionServiceClient" + }, + "fullName": "google.cloud.retail_v2alpha.GenerativeQuestionServiceClient.update_generative_questions_feature_config", + "method": { + "fullName": "google.cloud.retail.v2alpha.GenerativeQuestionService.UpdateGenerativeQuestionsFeatureConfig", + "service": { + "fullName": "google.cloud.retail.v2alpha.GenerativeQuestionService", + "shortName": "GenerativeQuestionService" + }, + "shortName": "UpdateGenerativeQuestionsFeatureConfig" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.retail_v2alpha.types.UpdateGenerativeQuestionsFeatureConfigRequest" + }, + { + "name": "generative_questions_feature_config", + "type": "google.cloud.retail_v2alpha.types.GenerativeQuestionsFeatureConfig" + }, + { + "name": "update_mask", + "type": "google.protobuf.field_mask_pb2.FieldMask" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.cloud.retail_v2alpha.types.GenerativeQuestionsFeatureConfig", + "shortName": "update_generative_questions_feature_config" + }, + "description": "Sample for UpdateGenerativeQuestionsFeatureConfig", + "file": "retail_v2alpha_generated_generative_question_service_update_generative_questions_feature_config_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "retail_v2alpha_generated_GenerativeQuestionService_UpdateGenerativeQuestionsFeatureConfig_sync", + "segments": [ + { + "end": 54, + "start": 27, + "type": "FULL" + }, + { + "end": 54, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 48, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 51, + "start": 49, + "type": "REQUEST_EXECUTION" + }, + { + "end": 55, + "start": 52, + "type": "RESPONSE_HANDLING" + } + ], + "title": "retail_v2alpha_generated_generative_question_service_update_generative_questions_feature_config_sync.py" + }, { "canonical": true, "clientMethod": { @@ -5822,7 +6651,176 @@ "type": "google.cloud.retail_v2alpha.types.Product" }, { - "name": "product_id", + "name": "product_id", + "type": "str" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.cloud.retail_v2alpha.types.Product", + "shortName": "create_product" + }, + "description": "Sample for CreateProduct", + "file": "retail_v2alpha_generated_product_service_create_product_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "retail_v2alpha_generated_ProductService_CreateProduct_async", + "segments": [ + { + "end": 56, + "start": 27, + "type": "FULL" + }, + { + "end": 56, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 50, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 53, + "start": 51, + "type": "REQUEST_EXECUTION" + }, + { + "end": 57, + "start": 54, + "type": "RESPONSE_HANDLING" + } + ], + "title": "retail_v2alpha_generated_product_service_create_product_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.retail_v2alpha.ProductServiceClient", + "shortName": "ProductServiceClient" + }, + "fullName": "google.cloud.retail_v2alpha.ProductServiceClient.create_product", + "method": { + "fullName": "google.cloud.retail.v2alpha.ProductService.CreateProduct", + "service": { + "fullName": "google.cloud.retail.v2alpha.ProductService", + "shortName": "ProductService" + }, + "shortName": "CreateProduct" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.retail_v2alpha.types.CreateProductRequest" + }, + { + "name": "parent", + "type": "str" + }, + { + "name": "product", + "type": "google.cloud.retail_v2alpha.types.Product" + }, + { + "name": "product_id", + "type": "str" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.cloud.retail_v2alpha.types.Product", + "shortName": "create_product" + }, + "description": "Sample for CreateProduct", + "file": "retail_v2alpha_generated_product_service_create_product_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "retail_v2alpha_generated_ProductService_CreateProduct_sync", + "segments": [ + { + "end": 56, + "start": 27, + "type": "FULL" + }, + { + "end": 56, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 50, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 53, + "start": 51, + "type": "REQUEST_EXECUTION" + }, + { + "end": 57, + "start": 54, + "type": "RESPONSE_HANDLING" + } + ], + "title": "retail_v2alpha_generated_product_service_create_product_sync.py" + }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.retail_v2alpha.ProductServiceAsyncClient", + "shortName": "ProductServiceAsyncClient" + }, + "fullName": "google.cloud.retail_v2alpha.ProductServiceAsyncClient.delete_product", + "method": { + "fullName": "google.cloud.retail.v2alpha.ProductService.DeleteProduct", + "service": { + "fullName": "google.cloud.retail.v2alpha.ProductService", + "shortName": "ProductService" + }, + "shortName": "DeleteProduct" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.retail_v2alpha.types.DeleteProductRequest" + }, + { + "name": "name", "type": "str" }, { @@ -5838,22 +6836,21 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.retail_v2alpha.types.Product", - "shortName": "create_product" + "shortName": "delete_product" }, - "description": "Sample for CreateProduct", - "file": "retail_v2alpha_generated_product_service_create_product_async.py", + "description": "Sample for DeleteProduct", + "file": "retail_v2alpha_generated_product_service_delete_product_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "retail_v2alpha_generated_ProductService_CreateProduct_async", + "regionTag": "retail_v2alpha_generated_ProductService_DeleteProduct_async", "segments": [ { - "end": 56, + "end": 49, "start": 27, "type": "FULL" }, { - "end": 56, + "end": 49, "start": 27, "type": "SHORT" }, @@ -5863,22 +6860,20 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 50, + "end": 45, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 53, - "start": 51, + "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 57, - "start": 54, + "end": 50, "type": "RESPONSE_HANDLING" } ], - "title": "retail_v2alpha_generated_product_service_create_product_async.py" + "title": "retail_v2alpha_generated_product_service_delete_product_async.py" }, { "canonical": true, @@ -5887,30 +6882,22 @@ "fullName": "google.cloud.retail_v2alpha.ProductServiceClient", "shortName": "ProductServiceClient" }, - "fullName": "google.cloud.retail_v2alpha.ProductServiceClient.create_product", + "fullName": "google.cloud.retail_v2alpha.ProductServiceClient.delete_product", "method": { - "fullName": "google.cloud.retail.v2alpha.ProductService.CreateProduct", + "fullName": "google.cloud.retail.v2alpha.ProductService.DeleteProduct", "service": { "fullName": "google.cloud.retail.v2alpha.ProductService", "shortName": "ProductService" }, - "shortName": "CreateProduct" + "shortName": "DeleteProduct" }, "parameters": [ { "name": "request", - "type": "google.cloud.retail_v2alpha.types.CreateProductRequest" - }, - { - "name": "parent", - "type": "str" - }, - { - "name": "product", - "type": "google.cloud.retail_v2alpha.types.Product" + "type": "google.cloud.retail_v2alpha.types.DeleteProductRequest" }, { - "name": "product_id", + "name": "name", "type": "str" }, { @@ -5926,22 +6913,21 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.retail_v2alpha.types.Product", - "shortName": "create_product" + "shortName": "delete_product" }, - "description": "Sample for CreateProduct", - "file": "retail_v2alpha_generated_product_service_create_product_sync.py", + "description": "Sample for DeleteProduct", + "file": "retail_v2alpha_generated_product_service_delete_product_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "retail_v2alpha_generated_ProductService_CreateProduct_sync", + "regionTag": "retail_v2alpha_generated_ProductService_DeleteProduct_sync", "segments": [ { - "end": 56, + "end": 49, "start": 27, "type": "FULL" }, { - "end": 56, + "end": 49, "start": 27, "type": "SHORT" }, @@ -5951,22 +6937,20 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 50, + "end": 45, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 53, - "start": 51, + "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 57, - "start": 54, + "end": 50, "type": "RESPONSE_HANDLING" } ], - "title": "retail_v2alpha_generated_product_service_create_product_sync.py" + "title": "retail_v2alpha_generated_product_service_delete_product_sync.py" }, { "canonical": true, @@ -5976,23 +6960,19 @@ "fullName": "google.cloud.retail_v2alpha.ProductServiceAsyncClient", "shortName": "ProductServiceAsyncClient" }, - "fullName": "google.cloud.retail_v2alpha.ProductServiceAsyncClient.delete_product", + "fullName": "google.cloud.retail_v2alpha.ProductServiceAsyncClient.export_products", "method": { - "fullName": "google.cloud.retail.v2alpha.ProductService.DeleteProduct", + "fullName": "google.cloud.retail.v2alpha.ProductService.ExportProducts", "service": { "fullName": "google.cloud.retail.v2alpha.ProductService", "shortName": "ProductService" }, - "shortName": "DeleteProduct" + "shortName": "ExportProducts" }, "parameters": [ { "name": "request", - "type": "google.cloud.retail_v2alpha.types.DeleteProductRequest" - }, - { - "name": "name", - "type": "str" + "type": "google.cloud.retail_v2alpha.types.ExportProductsRequest" }, { "name": "retry", @@ -6007,21 +6987,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "shortName": "delete_product" + "resultType": "google.api_core.operation_async.AsyncOperation", + "shortName": "export_products" }, - "description": "Sample for DeleteProduct", - "file": "retail_v2alpha_generated_product_service_delete_product_async.py", + "description": "Sample for ExportProducts", + "file": "retail_v2alpha_generated_product_service_export_products_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "retail_v2alpha_generated_ProductService_DeleteProduct_async", + "regionTag": "retail_v2alpha_generated_ProductService_ExportProducts_async", "segments": [ { - "end": 49, + "end": 59, "start": 27, "type": "FULL" }, { - "end": 49, + "end": 59, "start": 27, "type": "SHORT" }, @@ -6031,20 +7012,22 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 45, + "end": 49, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "start": 46, + "end": 56, + "start": 50, "type": "REQUEST_EXECUTION" }, { - "end": 50, + "end": 60, + "start": 57, "type": "RESPONSE_HANDLING" } ], - "title": "retail_v2alpha_generated_product_service_delete_product_async.py" + "title": "retail_v2alpha_generated_product_service_export_products_async.py" }, { "canonical": true, @@ -6053,23 +7036,19 @@ "fullName": "google.cloud.retail_v2alpha.ProductServiceClient", "shortName": "ProductServiceClient" }, - "fullName": "google.cloud.retail_v2alpha.ProductServiceClient.delete_product", + "fullName": "google.cloud.retail_v2alpha.ProductServiceClient.export_products", "method": { - "fullName": "google.cloud.retail.v2alpha.ProductService.DeleteProduct", + "fullName": "google.cloud.retail.v2alpha.ProductService.ExportProducts", "service": { "fullName": "google.cloud.retail.v2alpha.ProductService", "shortName": "ProductService" }, - "shortName": "DeleteProduct" + "shortName": "ExportProducts" }, "parameters": [ { "name": "request", - "type": "google.cloud.retail_v2alpha.types.DeleteProductRequest" - }, - { - "name": "name", - "type": "str" + "type": "google.cloud.retail_v2alpha.types.ExportProductsRequest" }, { "name": "retry", @@ -6084,21 +7063,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "shortName": "delete_product" + "resultType": "google.api_core.operation.Operation", + "shortName": "export_products" }, - "description": "Sample for DeleteProduct", - "file": "retail_v2alpha_generated_product_service_delete_product_sync.py", + "description": "Sample for ExportProducts", + "file": "retail_v2alpha_generated_product_service_export_products_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "retail_v2alpha_generated_ProductService_DeleteProduct_sync", + "regionTag": "retail_v2alpha_generated_ProductService_ExportProducts_sync", "segments": [ { - "end": 49, + "end": 59, "start": 27, "type": "FULL" }, { - "end": 49, + "end": 59, "start": 27, "type": "SHORT" }, @@ -6108,20 +7088,22 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 45, + "end": 49, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "start": 46, + "end": 56, + "start": 50, "type": "REQUEST_EXECUTION" }, { - "end": 50, + "end": 60, + "start": 57, "type": "RESPONSE_HANDLING" } ], - "title": "retail_v2alpha_generated_product_service_delete_product_sync.py" + "title": "retail_v2alpha_generated_product_service_export_products_sync.py" }, { "canonical": true, @@ -10158,6 +11140,159 @@ ], "title": "retail_v2alpha_generated_user_event_service_collect_user_event_sync.py" }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.retail_v2alpha.UserEventServiceAsyncClient", + "shortName": "UserEventServiceAsyncClient" + }, + "fullName": "google.cloud.retail_v2alpha.UserEventServiceAsyncClient.export_user_events", + "method": { + "fullName": "google.cloud.retail.v2alpha.UserEventService.ExportUserEvents", + "service": { + "fullName": "google.cloud.retail.v2alpha.UserEventService", + "shortName": "UserEventService" + }, + "shortName": "ExportUserEvents" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.retail_v2alpha.types.ExportUserEventsRequest" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.api_core.operation_async.AsyncOperation", + "shortName": "export_user_events" + }, + "description": "Sample for ExportUserEvents", + "file": "retail_v2alpha_generated_user_event_service_export_user_events_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "retail_v2alpha_generated_UserEventService_ExportUserEvents_async", + "segments": [ + { + "end": 59, + "start": 27, + "type": "FULL" + }, + { + "end": 59, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 49, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 56, + "start": 50, + "type": "REQUEST_EXECUTION" + }, + { + "end": 60, + "start": 57, + "type": "RESPONSE_HANDLING" + } + ], + "title": "retail_v2alpha_generated_user_event_service_export_user_events_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.retail_v2alpha.UserEventServiceClient", + "shortName": "UserEventServiceClient" + }, + "fullName": "google.cloud.retail_v2alpha.UserEventServiceClient.export_user_events", + "method": { + "fullName": "google.cloud.retail.v2alpha.UserEventService.ExportUserEvents", + "service": { + "fullName": "google.cloud.retail.v2alpha.UserEventService", + "shortName": "UserEventService" + }, + "shortName": "ExportUserEvents" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.retail_v2alpha.types.ExportUserEventsRequest" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.api_core.operation.Operation", + "shortName": "export_user_events" + }, + "description": "Sample for ExportUserEvents", + "file": "retail_v2alpha_generated_user_event_service_export_user_events_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "retail_v2alpha_generated_UserEventService_ExportUserEvents_sync", + "segments": [ + { + "end": 59, + "start": 27, + "type": "FULL" + }, + { + "end": 59, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 49, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 56, + "start": 50, + "type": "REQUEST_EXECUTION" + }, + { + "end": 60, + "start": 57, + "type": "RESPONSE_HANDLING" + } + ], + "title": "retail_v2alpha_generated_user_event_service_export_user_events_sync.py" + }, { "canonical": true, "clientMethod": { diff --git a/packages/google-cloud-retail/samples/generated_samples/snippet_metadata_google.cloud.retail.v2beta.json b/packages/google-cloud-retail/samples/generated_samples/snippet_metadata_google.cloud.retail.v2beta.json index 112a4d73f6b4..7d1d63860fc2 100644 --- a/packages/google-cloud-retail/samples/generated_samples/snippet_metadata_google.cloud.retail.v2beta.json +++ b/packages/google-cloud-retail/samples/generated_samples/snippet_metadata_google.cloud.retail.v2beta.json @@ -3216,30 +3216,30 @@ "clientMethod": { "async": true, "client": { - "fullName": "google.cloud.retail_v2beta.ModelServiceAsyncClient", - "shortName": "ModelServiceAsyncClient" + "fullName": "google.cloud.retail_v2beta.GenerativeQuestionServiceAsyncClient", + "shortName": "GenerativeQuestionServiceAsyncClient" }, - "fullName": "google.cloud.retail_v2beta.ModelServiceAsyncClient.create_model", + "fullName": "google.cloud.retail_v2beta.GenerativeQuestionServiceAsyncClient.batch_update_generative_question_configs", "method": { - "fullName": "google.cloud.retail.v2beta.ModelService.CreateModel", + "fullName": "google.cloud.retail.v2beta.GenerativeQuestionService.BatchUpdateGenerativeQuestionConfigs", "service": { - "fullName": "google.cloud.retail.v2beta.ModelService", - "shortName": "ModelService" + "fullName": "google.cloud.retail.v2beta.GenerativeQuestionService", + "shortName": "GenerativeQuestionService" }, - "shortName": "CreateModel" + "shortName": "BatchUpdateGenerativeQuestionConfigs" }, "parameters": [ { "name": "request", - "type": "google.cloud.retail_v2beta.types.CreateModelRequest" + "type": "google.cloud.retail_v2beta.types.BatchUpdateGenerativeQuestionConfigsRequest" }, { "name": "parent", "type": "str" }, { - "name": "model", - "type": "google.cloud.retail_v2beta.types.Model" + "name": "requests", + "type": "MutableSequence[google.cloud.retail_v2beta.types.UpdateGenerativeQuestionConfigRequest]" }, { "name": "retry", @@ -3254,22 +3254,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.api_core.operation_async.AsyncOperation", - "shortName": "create_model" + "resultType": "google.cloud.retail_v2beta.types.BatchUpdateGenerativeQuestionConfigsResponse", + "shortName": "batch_update_generative_question_configs" }, - "description": "Sample for CreateModel", - "file": "retail_v2beta_generated_model_service_create_model_async.py", + "description": "Sample for BatchUpdateGenerativeQuestionConfigs", + "file": "retail_v2beta_generated_generative_question_service_batch_update_generative_question_configs_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "retail_v2beta_generated_ModelService_CreateModel_async", + "regionTag": "retail_v2beta_generated_GenerativeQuestionService_BatchUpdateGenerativeQuestionConfigs_async", "segments": [ { - "end": 61, + "end": 55, "start": 27, "type": "FULL" }, { - "end": 61, + "end": 55, "start": 27, "type": "SHORT" }, @@ -3279,51 +3279,51 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 51, + "end": 49, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 58, - "start": 52, + "end": 52, + "start": 50, "type": "REQUEST_EXECUTION" }, { - "end": 62, - "start": 59, + "end": 56, + "start": 53, "type": "RESPONSE_HANDLING" } ], - "title": "retail_v2beta_generated_model_service_create_model_async.py" + "title": "retail_v2beta_generated_generative_question_service_batch_update_generative_question_configs_async.py" }, { "canonical": true, "clientMethod": { "client": { - "fullName": "google.cloud.retail_v2beta.ModelServiceClient", - "shortName": "ModelServiceClient" + "fullName": "google.cloud.retail_v2beta.GenerativeQuestionServiceClient", + "shortName": "GenerativeQuestionServiceClient" }, - "fullName": "google.cloud.retail_v2beta.ModelServiceClient.create_model", + "fullName": "google.cloud.retail_v2beta.GenerativeQuestionServiceClient.batch_update_generative_question_configs", "method": { - "fullName": "google.cloud.retail.v2beta.ModelService.CreateModel", + "fullName": "google.cloud.retail.v2beta.GenerativeQuestionService.BatchUpdateGenerativeQuestionConfigs", "service": { - "fullName": "google.cloud.retail.v2beta.ModelService", - "shortName": "ModelService" + "fullName": "google.cloud.retail.v2beta.GenerativeQuestionService", + "shortName": "GenerativeQuestionService" }, - "shortName": "CreateModel" + "shortName": "BatchUpdateGenerativeQuestionConfigs" }, "parameters": [ { "name": "request", - "type": "google.cloud.retail_v2beta.types.CreateModelRequest" + "type": "google.cloud.retail_v2beta.types.BatchUpdateGenerativeQuestionConfigsRequest" }, { "name": "parent", "type": "str" }, { - "name": "model", - "type": "google.cloud.retail_v2beta.types.Model" + "name": "requests", + "type": "MutableSequence[google.cloud.retail_v2beta.types.UpdateGenerativeQuestionConfigRequest]" }, { "name": "retry", @@ -3338,22 +3338,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.api_core.operation.Operation", - "shortName": "create_model" + "resultType": "google.cloud.retail_v2beta.types.BatchUpdateGenerativeQuestionConfigsResponse", + "shortName": "batch_update_generative_question_configs" }, - "description": "Sample for CreateModel", - "file": "retail_v2beta_generated_model_service_create_model_sync.py", + "description": "Sample for BatchUpdateGenerativeQuestionConfigs", + "file": "retail_v2beta_generated_generative_question_service_batch_update_generative_question_configs_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "retail_v2beta_generated_ModelService_CreateModel_sync", + "regionTag": "retail_v2beta_generated_GenerativeQuestionService_BatchUpdateGenerativeQuestionConfigs_sync", "segments": [ { - "end": 61, + "end": 55, "start": 27, "type": "FULL" }, { - "end": 61, + "end": 55, "start": 27, "type": "SHORT" }, @@ -3363,47 +3363,47 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 51, + "end": 49, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 58, - "start": 52, + "end": 52, + "start": 50, "type": "REQUEST_EXECUTION" }, { - "end": 62, - "start": 59, + "end": 56, + "start": 53, "type": "RESPONSE_HANDLING" } ], - "title": "retail_v2beta_generated_model_service_create_model_sync.py" + "title": "retail_v2beta_generated_generative_question_service_batch_update_generative_question_configs_sync.py" }, { "canonical": true, "clientMethod": { "async": true, "client": { - "fullName": "google.cloud.retail_v2beta.ModelServiceAsyncClient", - "shortName": "ModelServiceAsyncClient" + "fullName": "google.cloud.retail_v2beta.GenerativeQuestionServiceAsyncClient", + "shortName": "GenerativeQuestionServiceAsyncClient" }, - "fullName": "google.cloud.retail_v2beta.ModelServiceAsyncClient.delete_model", + "fullName": "google.cloud.retail_v2beta.GenerativeQuestionServiceAsyncClient.get_generative_questions_feature_config", "method": { - "fullName": "google.cloud.retail.v2beta.ModelService.DeleteModel", + "fullName": "google.cloud.retail.v2beta.GenerativeQuestionService.GetGenerativeQuestionsFeatureConfig", "service": { - "fullName": "google.cloud.retail.v2beta.ModelService", - "shortName": "ModelService" + "fullName": "google.cloud.retail.v2beta.GenerativeQuestionService", + "shortName": "GenerativeQuestionService" }, - "shortName": "DeleteModel" + "shortName": "GetGenerativeQuestionsFeatureConfig" }, "parameters": [ { "name": "request", - "type": "google.cloud.retail_v2beta.types.DeleteModelRequest" + "type": "google.cloud.retail_v2beta.types.GetGenerativeQuestionsFeatureConfigRequest" }, { - "name": "name", + "name": "catalog", "type": "str" }, { @@ -3419,21 +3419,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "shortName": "delete_model" + "resultType": "google.cloud.retail_v2beta.types.GenerativeQuestionsFeatureConfig", + "shortName": "get_generative_questions_feature_config" }, - "description": "Sample for DeleteModel", - "file": "retail_v2beta_generated_model_service_delete_model_async.py", + "description": "Sample for GetGenerativeQuestionsFeatureConfig", + "file": "retail_v2beta_generated_generative_question_service_get_generative_questions_feature_config_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "retail_v2beta_generated_ModelService_DeleteModel_async", + "regionTag": "retail_v2beta_generated_GenerativeQuestionService_GetGenerativeQuestionsFeatureConfig_async", "segments": [ { - "end": 49, + "end": 51, "start": 27, "type": "FULL" }, { - "end": 49, + "end": 51, "start": 27, "type": "SHORT" }, @@ -3448,39 +3449,41 @@ "type": "REQUEST_INITIALIZATION" }, { + "end": 48, "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 50, + "end": 52, + "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "retail_v2beta_generated_model_service_delete_model_async.py" + "title": "retail_v2beta_generated_generative_question_service_get_generative_questions_feature_config_async.py" }, { "canonical": true, "clientMethod": { "client": { - "fullName": "google.cloud.retail_v2beta.ModelServiceClient", - "shortName": "ModelServiceClient" + "fullName": "google.cloud.retail_v2beta.GenerativeQuestionServiceClient", + "shortName": "GenerativeQuestionServiceClient" }, - "fullName": "google.cloud.retail_v2beta.ModelServiceClient.delete_model", + "fullName": "google.cloud.retail_v2beta.GenerativeQuestionServiceClient.get_generative_questions_feature_config", "method": { - "fullName": "google.cloud.retail.v2beta.ModelService.DeleteModel", + "fullName": "google.cloud.retail.v2beta.GenerativeQuestionService.GetGenerativeQuestionsFeatureConfig", "service": { - "fullName": "google.cloud.retail.v2beta.ModelService", - "shortName": "ModelService" + "fullName": "google.cloud.retail.v2beta.GenerativeQuestionService", + "shortName": "GenerativeQuestionService" }, - "shortName": "DeleteModel" + "shortName": "GetGenerativeQuestionsFeatureConfig" }, "parameters": [ { "name": "request", - "type": "google.cloud.retail_v2beta.types.DeleteModelRequest" + "type": "google.cloud.retail_v2beta.types.GetGenerativeQuestionsFeatureConfigRequest" }, { - "name": "name", + "name": "catalog", "type": "str" }, { @@ -3496,21 +3499,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "shortName": "delete_model" + "resultType": "google.cloud.retail_v2beta.types.GenerativeQuestionsFeatureConfig", + "shortName": "get_generative_questions_feature_config" }, - "description": "Sample for DeleteModel", - "file": "retail_v2beta_generated_model_service_delete_model_sync.py", + "description": "Sample for GetGenerativeQuestionsFeatureConfig", + "file": "retail_v2beta_generated_generative_question_service_get_generative_questions_feature_config_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "retail_v2beta_generated_ModelService_DeleteModel_sync", + "regionTag": "retail_v2beta_generated_GenerativeQuestionService_GetGenerativeQuestionsFeatureConfig_sync", "segments": [ { - "end": 49, + "end": 51, "start": 27, "type": "FULL" }, { - "end": 49, + "end": 51, "start": 27, "type": "SHORT" }, @@ -3525,40 +3529,42 @@ "type": "REQUEST_INITIALIZATION" }, { + "end": 48, "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 50, + "end": 52, + "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "retail_v2beta_generated_model_service_delete_model_sync.py" + "title": "retail_v2beta_generated_generative_question_service_get_generative_questions_feature_config_sync.py" }, { "canonical": true, "clientMethod": { "async": true, "client": { - "fullName": "google.cloud.retail_v2beta.ModelServiceAsyncClient", - "shortName": "ModelServiceAsyncClient" + "fullName": "google.cloud.retail_v2beta.GenerativeQuestionServiceAsyncClient", + "shortName": "GenerativeQuestionServiceAsyncClient" }, - "fullName": "google.cloud.retail_v2beta.ModelServiceAsyncClient.get_model", + "fullName": "google.cloud.retail_v2beta.GenerativeQuestionServiceAsyncClient.list_generative_question_configs", "method": { - "fullName": "google.cloud.retail.v2beta.ModelService.GetModel", + "fullName": "google.cloud.retail.v2beta.GenerativeQuestionService.ListGenerativeQuestionConfigs", "service": { - "fullName": "google.cloud.retail.v2beta.ModelService", - "shortName": "ModelService" + "fullName": "google.cloud.retail.v2beta.GenerativeQuestionService", + "shortName": "GenerativeQuestionService" }, - "shortName": "GetModel" + "shortName": "ListGenerativeQuestionConfigs" }, "parameters": [ { "name": "request", - "type": "google.cloud.retail_v2beta.types.GetModelRequest" + "type": "google.cloud.retail_v2beta.types.ListGenerativeQuestionConfigsRequest" }, { - "name": "name", + "name": "parent", "type": "str" }, { @@ -3574,14 +3580,14 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.retail_v2beta.types.Model", - "shortName": "get_model" + "resultType": "google.cloud.retail_v2beta.types.ListGenerativeQuestionConfigsResponse", + "shortName": "list_generative_question_configs" }, - "description": "Sample for GetModel", - "file": "retail_v2beta_generated_model_service_get_model_async.py", + "description": "Sample for ListGenerativeQuestionConfigs", + "file": "retail_v2beta_generated_generative_question_service_list_generative_question_configs_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "retail_v2beta_generated_ModelService_GetModel_async", + "regionTag": "retail_v2beta_generated_GenerativeQuestionService_ListGenerativeQuestionConfigs_async", "segments": [ { "end": 51, @@ -3614,31 +3620,31 @@ "type": "RESPONSE_HANDLING" } ], - "title": "retail_v2beta_generated_model_service_get_model_async.py" + "title": "retail_v2beta_generated_generative_question_service_list_generative_question_configs_async.py" }, { "canonical": true, "clientMethod": { "client": { - "fullName": "google.cloud.retail_v2beta.ModelServiceClient", - "shortName": "ModelServiceClient" + "fullName": "google.cloud.retail_v2beta.GenerativeQuestionServiceClient", + "shortName": "GenerativeQuestionServiceClient" }, - "fullName": "google.cloud.retail_v2beta.ModelServiceClient.get_model", + "fullName": "google.cloud.retail_v2beta.GenerativeQuestionServiceClient.list_generative_question_configs", "method": { - "fullName": "google.cloud.retail.v2beta.ModelService.GetModel", + "fullName": "google.cloud.retail.v2beta.GenerativeQuestionService.ListGenerativeQuestionConfigs", "service": { - "fullName": "google.cloud.retail.v2beta.ModelService", - "shortName": "ModelService" + "fullName": "google.cloud.retail.v2beta.GenerativeQuestionService", + "shortName": "GenerativeQuestionService" }, - "shortName": "GetModel" + "shortName": "ListGenerativeQuestionConfigs" }, "parameters": [ { "name": "request", - "type": "google.cloud.retail_v2beta.types.GetModelRequest" + "type": "google.cloud.retail_v2beta.types.ListGenerativeQuestionConfigsRequest" }, { - "name": "name", + "name": "parent", "type": "str" }, { @@ -3654,14 +3660,14 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.retail_v2beta.types.Model", - "shortName": "get_model" + "resultType": "google.cloud.retail_v2beta.types.ListGenerativeQuestionConfigsResponse", + "shortName": "list_generative_question_configs" }, - "description": "Sample for GetModel", - "file": "retail_v2beta_generated_model_service_get_model_sync.py", + "description": "Sample for ListGenerativeQuestionConfigs", + "file": "retail_v2beta_generated_generative_question_service_list_generative_question_configs_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "retail_v2beta_generated_ModelService_GetModel_sync", + "regionTag": "retail_v2beta_generated_GenerativeQuestionService_ListGenerativeQuestionConfigs_sync", "segments": [ { "end": 51, @@ -3694,33 +3700,37 @@ "type": "RESPONSE_HANDLING" } ], - "title": "retail_v2beta_generated_model_service_get_model_sync.py" + "title": "retail_v2beta_generated_generative_question_service_list_generative_question_configs_sync.py" }, { "canonical": true, "clientMethod": { "async": true, "client": { - "fullName": "google.cloud.retail_v2beta.ModelServiceAsyncClient", - "shortName": "ModelServiceAsyncClient" + "fullName": "google.cloud.retail_v2beta.GenerativeQuestionServiceAsyncClient", + "shortName": "GenerativeQuestionServiceAsyncClient" }, - "fullName": "google.cloud.retail_v2beta.ModelServiceAsyncClient.list_models", + "fullName": "google.cloud.retail_v2beta.GenerativeQuestionServiceAsyncClient.update_generative_question_config", "method": { - "fullName": "google.cloud.retail.v2beta.ModelService.ListModels", + "fullName": "google.cloud.retail.v2beta.GenerativeQuestionService.UpdateGenerativeQuestionConfig", "service": { - "fullName": "google.cloud.retail.v2beta.ModelService", - "shortName": "ModelService" + "fullName": "google.cloud.retail.v2beta.GenerativeQuestionService", + "shortName": "GenerativeQuestionService" }, - "shortName": "ListModels" + "shortName": "UpdateGenerativeQuestionConfig" }, "parameters": [ { "name": "request", - "type": "google.cloud.retail_v2beta.types.ListModelsRequest" + "type": "google.cloud.retail_v2beta.types.UpdateGenerativeQuestionConfigRequest" }, { - "name": "parent", - "type": "str" + "name": "generative_question_config", + "type": "google.cloud.retail_v2beta.types.GenerativeQuestionConfig" + }, + { + "name": "update_mask", + "type": "google.protobuf.field_mask_pb2.FieldMask" }, { "name": "retry", @@ -3735,22 +3745,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.retail_v2beta.services.model_service.pagers.ListModelsAsyncPager", - "shortName": "list_models" + "resultType": "google.cloud.retail_v2beta.types.GenerativeQuestionConfig", + "shortName": "update_generative_question_config" }, - "description": "Sample for ListModels", - "file": "retail_v2beta_generated_model_service_list_models_async.py", + "description": "Sample for UpdateGenerativeQuestionConfig", + "file": "retail_v2beta_generated_generative_question_service_update_generative_question_config_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "retail_v2beta_generated_ModelService_ListModels_async", + "regionTag": "retail_v2beta_generated_GenerativeQuestionService_UpdateGenerativeQuestionConfig_async", "segments": [ { - "end": 52, + "end": 55, "start": 27, "type": "FULL" }, { - "end": 52, + "end": 55, "start": 27, "type": "SHORT" }, @@ -3760,47 +3770,51 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 45, + "end": 49, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 48, - "start": 46, + "end": 52, + "start": 50, "type": "REQUEST_EXECUTION" }, { - "end": 53, - "start": 49, + "end": 56, + "start": 53, "type": "RESPONSE_HANDLING" } ], - "title": "retail_v2beta_generated_model_service_list_models_async.py" + "title": "retail_v2beta_generated_generative_question_service_update_generative_question_config_async.py" }, { "canonical": true, "clientMethod": { "client": { - "fullName": "google.cloud.retail_v2beta.ModelServiceClient", - "shortName": "ModelServiceClient" + "fullName": "google.cloud.retail_v2beta.GenerativeQuestionServiceClient", + "shortName": "GenerativeQuestionServiceClient" }, - "fullName": "google.cloud.retail_v2beta.ModelServiceClient.list_models", + "fullName": "google.cloud.retail_v2beta.GenerativeQuestionServiceClient.update_generative_question_config", "method": { - "fullName": "google.cloud.retail.v2beta.ModelService.ListModels", + "fullName": "google.cloud.retail.v2beta.GenerativeQuestionService.UpdateGenerativeQuestionConfig", "service": { - "fullName": "google.cloud.retail.v2beta.ModelService", - "shortName": "ModelService" + "fullName": "google.cloud.retail.v2beta.GenerativeQuestionService", + "shortName": "GenerativeQuestionService" }, - "shortName": "ListModels" + "shortName": "UpdateGenerativeQuestionConfig" }, "parameters": [ { "name": "request", - "type": "google.cloud.retail_v2beta.types.ListModelsRequest" + "type": "google.cloud.retail_v2beta.types.UpdateGenerativeQuestionConfigRequest" }, { - "name": "parent", - "type": "str" + "name": "generative_question_config", + "type": "google.cloud.retail_v2beta.types.GenerativeQuestionConfig" + }, + { + "name": "update_mask", + "type": "google.protobuf.field_mask_pb2.FieldMask" }, { "name": "retry", @@ -3815,22 +3829,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.retail_v2beta.services.model_service.pagers.ListModelsPager", - "shortName": "list_models" + "resultType": "google.cloud.retail_v2beta.types.GenerativeQuestionConfig", + "shortName": "update_generative_question_config" }, - "description": "Sample for ListModels", - "file": "retail_v2beta_generated_model_service_list_models_sync.py", + "description": "Sample for UpdateGenerativeQuestionConfig", + "file": "retail_v2beta_generated_generative_question_service_update_generative_question_config_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "retail_v2beta_generated_ModelService_ListModels_sync", + "regionTag": "retail_v2beta_generated_GenerativeQuestionService_UpdateGenerativeQuestionConfig_sync", "segments": [ { - "end": 52, + "end": 55, "start": 27, "type": "FULL" }, { - "end": 52, + "end": 55, "start": 27, "type": "SHORT" }, @@ -3840,48 +3854,52 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 45, + "end": 49, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 48, - "start": 46, + "end": 52, + "start": 50, "type": "REQUEST_EXECUTION" }, { - "end": 53, - "start": 49, + "end": 56, + "start": 53, "type": "RESPONSE_HANDLING" } ], - "title": "retail_v2beta_generated_model_service_list_models_sync.py" + "title": "retail_v2beta_generated_generative_question_service_update_generative_question_config_sync.py" }, { "canonical": true, "clientMethod": { "async": true, "client": { - "fullName": "google.cloud.retail_v2beta.ModelServiceAsyncClient", - "shortName": "ModelServiceAsyncClient" + "fullName": "google.cloud.retail_v2beta.GenerativeQuestionServiceAsyncClient", + "shortName": "GenerativeQuestionServiceAsyncClient" }, - "fullName": "google.cloud.retail_v2beta.ModelServiceAsyncClient.pause_model", + "fullName": "google.cloud.retail_v2beta.GenerativeQuestionServiceAsyncClient.update_generative_questions_feature_config", "method": { - "fullName": "google.cloud.retail.v2beta.ModelService.PauseModel", + "fullName": "google.cloud.retail.v2beta.GenerativeQuestionService.UpdateGenerativeQuestionsFeatureConfig", "service": { - "fullName": "google.cloud.retail.v2beta.ModelService", - "shortName": "ModelService" + "fullName": "google.cloud.retail.v2beta.GenerativeQuestionService", + "shortName": "GenerativeQuestionService" }, - "shortName": "PauseModel" + "shortName": "UpdateGenerativeQuestionsFeatureConfig" }, "parameters": [ { "name": "request", - "type": "google.cloud.retail_v2beta.types.PauseModelRequest" + "type": "google.cloud.retail_v2beta.types.UpdateGenerativeQuestionsFeatureConfigRequest" }, { - "name": "name", - "type": "str" + "name": "generative_questions_feature_config", + "type": "google.cloud.retail_v2beta.types.GenerativeQuestionsFeatureConfig" + }, + { + "name": "update_mask", + "type": "google.protobuf.field_mask_pb2.FieldMask" }, { "name": "retry", @@ -3896,22 +3914,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.retail_v2beta.types.Model", - "shortName": "pause_model" + "resultType": "google.cloud.retail_v2beta.types.GenerativeQuestionsFeatureConfig", + "shortName": "update_generative_questions_feature_config" }, - "description": "Sample for PauseModel", - "file": "retail_v2beta_generated_model_service_pause_model_async.py", + "description": "Sample for UpdateGenerativeQuestionsFeatureConfig", + "file": "retail_v2beta_generated_generative_question_service_update_generative_questions_feature_config_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "retail_v2beta_generated_ModelService_PauseModel_async", + "regionTag": "retail_v2beta_generated_GenerativeQuestionService_UpdateGenerativeQuestionsFeatureConfig_async", "segments": [ { - "end": 51, + "end": 54, "start": 27, "type": "FULL" }, { - "end": 51, + "end": 54, "start": 27, "type": "SHORT" }, @@ -3921,47 +3939,51 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 45, + "end": 48, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 48, - "start": 46, + "end": 51, + "start": 49, "type": "REQUEST_EXECUTION" }, { - "end": 52, - "start": 49, + "end": 55, + "start": 52, "type": "RESPONSE_HANDLING" } ], - "title": "retail_v2beta_generated_model_service_pause_model_async.py" + "title": "retail_v2beta_generated_generative_question_service_update_generative_questions_feature_config_async.py" }, { "canonical": true, "clientMethod": { "client": { - "fullName": "google.cloud.retail_v2beta.ModelServiceClient", - "shortName": "ModelServiceClient" + "fullName": "google.cloud.retail_v2beta.GenerativeQuestionServiceClient", + "shortName": "GenerativeQuestionServiceClient" }, - "fullName": "google.cloud.retail_v2beta.ModelServiceClient.pause_model", + "fullName": "google.cloud.retail_v2beta.GenerativeQuestionServiceClient.update_generative_questions_feature_config", "method": { - "fullName": "google.cloud.retail.v2beta.ModelService.PauseModel", + "fullName": "google.cloud.retail.v2beta.GenerativeQuestionService.UpdateGenerativeQuestionsFeatureConfig", "service": { - "fullName": "google.cloud.retail.v2beta.ModelService", - "shortName": "ModelService" + "fullName": "google.cloud.retail.v2beta.GenerativeQuestionService", + "shortName": "GenerativeQuestionService" }, - "shortName": "PauseModel" + "shortName": "UpdateGenerativeQuestionsFeatureConfig" }, "parameters": [ { "name": "request", - "type": "google.cloud.retail_v2beta.types.PauseModelRequest" + "type": "google.cloud.retail_v2beta.types.UpdateGenerativeQuestionsFeatureConfigRequest" }, { - "name": "name", - "type": "str" + "name": "generative_questions_feature_config", + "type": "google.cloud.retail_v2beta.types.GenerativeQuestionsFeatureConfig" + }, + { + "name": "update_mask", + "type": "google.protobuf.field_mask_pb2.FieldMask" }, { "name": "retry", @@ -3976,22 +3998,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.retail_v2beta.types.Model", - "shortName": "pause_model" + "resultType": "google.cloud.retail_v2beta.types.GenerativeQuestionsFeatureConfig", + "shortName": "update_generative_questions_feature_config" }, - "description": "Sample for PauseModel", - "file": "retail_v2beta_generated_model_service_pause_model_sync.py", + "description": "Sample for UpdateGenerativeQuestionsFeatureConfig", + "file": "retail_v2beta_generated_generative_question_service_update_generative_questions_feature_config_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "retail_v2beta_generated_ModelService_PauseModel_sync", + "regionTag": "retail_v2beta_generated_GenerativeQuestionService_UpdateGenerativeQuestionsFeatureConfig_sync", "segments": [ { - "end": 51, + "end": 54, "start": 27, "type": "FULL" }, { - "end": 51, + "end": 54, "start": 27, "type": "SHORT" }, @@ -4001,22 +4023,22 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 45, + "end": 48, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 48, - "start": 46, + "end": 51, + "start": 49, "type": "REQUEST_EXECUTION" }, { - "end": 52, - "start": 49, + "end": 55, + "start": 52, "type": "RESPONSE_HANDLING" } ], - "title": "retail_v2beta_generated_model_service_pause_model_sync.py" + "title": "retail_v2beta_generated_generative_question_service_update_generative_questions_feature_config_sync.py" }, { "canonical": true, @@ -4026,24 +4048,28 @@ "fullName": "google.cloud.retail_v2beta.ModelServiceAsyncClient", "shortName": "ModelServiceAsyncClient" }, - "fullName": "google.cloud.retail_v2beta.ModelServiceAsyncClient.resume_model", + "fullName": "google.cloud.retail_v2beta.ModelServiceAsyncClient.create_model", "method": { - "fullName": "google.cloud.retail.v2beta.ModelService.ResumeModel", + "fullName": "google.cloud.retail.v2beta.ModelService.CreateModel", "service": { "fullName": "google.cloud.retail.v2beta.ModelService", "shortName": "ModelService" }, - "shortName": "ResumeModel" + "shortName": "CreateModel" }, "parameters": [ { "name": "request", - "type": "google.cloud.retail_v2beta.types.ResumeModelRequest" + "type": "google.cloud.retail_v2beta.types.CreateModelRequest" }, { - "name": "name", + "name": "parent", "type": "str" }, + { + "name": "model", + "type": "google.cloud.retail_v2beta.types.Model" + }, { "name": "retry", "type": "google.api_core.retry.Retry" @@ -4057,22 +4083,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.retail_v2beta.types.Model", - "shortName": "resume_model" + "resultType": "google.api_core.operation_async.AsyncOperation", + "shortName": "create_model" }, - "description": "Sample for ResumeModel", - "file": "retail_v2beta_generated_model_service_resume_model_async.py", + "description": "Sample for CreateModel", + "file": "retail_v2beta_generated_model_service_create_model_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "retail_v2beta_generated_ModelService_ResumeModel_async", + "regionTag": "retail_v2beta_generated_ModelService_CreateModel_async", "segments": [ { - "end": 51, + "end": 61, "start": 27, "type": "FULL" }, { - "end": 51, + "end": 61, "start": 27, "type": "SHORT" }, @@ -4082,22 +4108,22 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 45, + "end": 51, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 48, - "start": 46, + "end": 58, + "start": 52, "type": "REQUEST_EXECUTION" }, { - "end": 52, - "start": 49, + "end": 62, + "start": 59, "type": "RESPONSE_HANDLING" } ], - "title": "retail_v2beta_generated_model_service_resume_model_async.py" + "title": "retail_v2beta_generated_model_service_create_model_async.py" }, { "canonical": true, @@ -4106,24 +4132,28 @@ "fullName": "google.cloud.retail_v2beta.ModelServiceClient", "shortName": "ModelServiceClient" }, - "fullName": "google.cloud.retail_v2beta.ModelServiceClient.resume_model", + "fullName": "google.cloud.retail_v2beta.ModelServiceClient.create_model", "method": { - "fullName": "google.cloud.retail.v2beta.ModelService.ResumeModel", + "fullName": "google.cloud.retail.v2beta.ModelService.CreateModel", "service": { "fullName": "google.cloud.retail.v2beta.ModelService", "shortName": "ModelService" }, - "shortName": "ResumeModel" + "shortName": "CreateModel" }, "parameters": [ { "name": "request", - "type": "google.cloud.retail_v2beta.types.ResumeModelRequest" + "type": "google.cloud.retail_v2beta.types.CreateModelRequest" }, { - "name": "name", + "name": "parent", "type": "str" }, + { + "name": "model", + "type": "google.cloud.retail_v2beta.types.Model" + }, { "name": "retry", "type": "google.api_core.retry.Retry" @@ -4137,22 +4167,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.retail_v2beta.types.Model", - "shortName": "resume_model" + "resultType": "google.api_core.operation.Operation", + "shortName": "create_model" }, - "description": "Sample for ResumeModel", - "file": "retail_v2beta_generated_model_service_resume_model_sync.py", + "description": "Sample for CreateModel", + "file": "retail_v2beta_generated_model_service_create_model_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "retail_v2beta_generated_ModelService_ResumeModel_sync", + "regionTag": "retail_v2beta_generated_ModelService_CreateModel_sync", "segments": [ { - "end": 51, + "end": 61, "start": 27, "type": "FULL" }, { - "end": 51, + "end": 61, "start": 27, "type": "SHORT" }, @@ -4162,22 +4192,22 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 45, + "end": 51, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 48, - "start": 46, + "end": 58, + "start": 52, "type": "REQUEST_EXECUTION" }, { - "end": 52, - "start": 49, + "end": 62, + "start": 59, "type": "RESPONSE_HANDLING" } ], - "title": "retail_v2beta_generated_model_service_resume_model_sync.py" + "title": "retail_v2beta_generated_model_service_create_model_sync.py" }, { "canonical": true, @@ -4187,19 +4217,19 @@ "fullName": "google.cloud.retail_v2beta.ModelServiceAsyncClient", "shortName": "ModelServiceAsyncClient" }, - "fullName": "google.cloud.retail_v2beta.ModelServiceAsyncClient.tune_model", + "fullName": "google.cloud.retail_v2beta.ModelServiceAsyncClient.delete_model", "method": { - "fullName": "google.cloud.retail.v2beta.ModelService.TuneModel", + "fullName": "google.cloud.retail.v2beta.ModelService.DeleteModel", "service": { "fullName": "google.cloud.retail.v2beta.ModelService", "shortName": "ModelService" }, - "shortName": "TuneModel" + "shortName": "DeleteModel" }, "parameters": [ { "name": "request", - "type": "google.cloud.retail_v2beta.types.TuneModelRequest" + "type": "google.cloud.retail_v2beta.types.DeleteModelRequest" }, { "name": "name", @@ -4218,22 +4248,21 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.api_core.operation_async.AsyncOperation", - "shortName": "tune_model" + "shortName": "delete_model" }, - "description": "Sample for TuneModel", - "file": "retail_v2beta_generated_model_service_tune_model_async.py", + "description": "Sample for DeleteModel", + "file": "retail_v2beta_generated_model_service_delete_model_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "retail_v2beta_generated_ModelService_TuneModel_async", + "regionTag": "retail_v2beta_generated_ModelService_DeleteModel_async", "segments": [ { - "end": 55, + "end": 49, "start": 27, "type": "FULL" }, { - "end": 55, + "end": 49, "start": 27, "type": "SHORT" }, @@ -4248,17 +4277,15 @@ "type": "REQUEST_INITIALIZATION" }, { - "end": 52, "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 56, - "start": 53, + "end": 50, "type": "RESPONSE_HANDLING" } ], - "title": "retail_v2beta_generated_model_service_tune_model_async.py" + "title": "retail_v2beta_generated_model_service_delete_model_async.py" }, { "canonical": true, @@ -4267,19 +4294,19 @@ "fullName": "google.cloud.retail_v2beta.ModelServiceClient", "shortName": "ModelServiceClient" }, - "fullName": "google.cloud.retail_v2beta.ModelServiceClient.tune_model", + "fullName": "google.cloud.retail_v2beta.ModelServiceClient.delete_model", "method": { - "fullName": "google.cloud.retail.v2beta.ModelService.TuneModel", + "fullName": "google.cloud.retail.v2beta.ModelService.DeleteModel", "service": { "fullName": "google.cloud.retail.v2beta.ModelService", "shortName": "ModelService" }, - "shortName": "TuneModel" + "shortName": "DeleteModel" }, "parameters": [ { "name": "request", - "type": "google.cloud.retail_v2beta.types.TuneModelRequest" + "type": "google.cloud.retail_v2beta.types.DeleteModelRequest" }, { "name": "name", @@ -4298,22 +4325,21 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.api_core.operation.Operation", - "shortName": "tune_model" + "shortName": "delete_model" }, - "description": "Sample for TuneModel", - "file": "retail_v2beta_generated_model_service_tune_model_sync.py", + "description": "Sample for DeleteModel", + "file": "retail_v2beta_generated_model_service_delete_model_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "retail_v2beta_generated_ModelService_TuneModel_sync", + "regionTag": "retail_v2beta_generated_ModelService_DeleteModel_sync", "segments": [ { - "end": 55, + "end": 49, "start": 27, "type": "FULL" }, { - "end": 55, + "end": 49, "start": 27, "type": "SHORT" }, @@ -4328,17 +4354,15 @@ "type": "REQUEST_INITIALIZATION" }, { - "end": 52, "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 56, - "start": 53, + "end": 50, "type": "RESPONSE_HANDLING" } ], - "title": "retail_v2beta_generated_model_service_tune_model_sync.py" + "title": "retail_v2beta_generated_model_service_delete_model_sync.py" }, { "canonical": true, @@ -4348,27 +4372,23 @@ "fullName": "google.cloud.retail_v2beta.ModelServiceAsyncClient", "shortName": "ModelServiceAsyncClient" }, - "fullName": "google.cloud.retail_v2beta.ModelServiceAsyncClient.update_model", + "fullName": "google.cloud.retail_v2beta.ModelServiceAsyncClient.get_model", "method": { - "fullName": "google.cloud.retail.v2beta.ModelService.UpdateModel", + "fullName": "google.cloud.retail.v2beta.ModelService.GetModel", "service": { "fullName": "google.cloud.retail.v2beta.ModelService", "shortName": "ModelService" }, - "shortName": "UpdateModel" + "shortName": "GetModel" }, "parameters": [ { "name": "request", - "type": "google.cloud.retail_v2beta.types.UpdateModelRequest" - }, - { - "name": "model", - "type": "google.cloud.retail_v2beta.types.Model" + "type": "google.cloud.retail_v2beta.types.GetModelRequest" }, { - "name": "update_mask", - "type": "google.protobuf.field_mask_pb2.FieldMask" + "name": "name", + "type": "str" }, { "name": "retry", @@ -4384,21 +4404,21 @@ } ], "resultType": "google.cloud.retail_v2beta.types.Model", - "shortName": "update_model" + "shortName": "get_model" }, - "description": "Sample for UpdateModel", - "file": "retail_v2beta_generated_model_service_update_model_async.py", + "description": "Sample for GetModel", + "file": "retail_v2beta_generated_model_service_get_model_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "retail_v2beta_generated_ModelService_UpdateModel_async", + "regionTag": "retail_v2beta_generated_ModelService_GetModel_async", "segments": [ { - "end": 56, + "end": 51, "start": 27, "type": "FULL" }, { - "end": 56, + "end": 51, "start": 27, "type": "SHORT" }, @@ -4408,22 +4428,22 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 50, + "end": 45, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 53, - "start": 51, + "end": 48, + "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 57, - "start": 54, + "end": 52, + "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "retail_v2beta_generated_model_service_update_model_async.py" + "title": "retail_v2beta_generated_model_service_get_model_async.py" }, { "canonical": true, @@ -4432,27 +4452,1311 @@ "fullName": "google.cloud.retail_v2beta.ModelServiceClient", "shortName": "ModelServiceClient" }, - "fullName": "google.cloud.retail_v2beta.ModelServiceClient.update_model", + "fullName": "google.cloud.retail_v2beta.ModelServiceClient.get_model", "method": { - "fullName": "google.cloud.retail.v2beta.ModelService.UpdateModel", + "fullName": "google.cloud.retail.v2beta.ModelService.GetModel", "service": { "fullName": "google.cloud.retail.v2beta.ModelService", "shortName": "ModelService" }, - "shortName": "UpdateModel" + "shortName": "GetModel" }, "parameters": [ { "name": "request", - "type": "google.cloud.retail_v2beta.types.UpdateModelRequest" + "type": "google.cloud.retail_v2beta.types.GetModelRequest" }, { - "name": "model", - "type": "google.cloud.retail_v2beta.types.Model" + "name": "name", + "type": "str" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.cloud.retail_v2beta.types.Model", + "shortName": "get_model" + }, + "description": "Sample for GetModel", + "file": "retail_v2beta_generated_model_service_get_model_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "retail_v2beta_generated_ModelService_GetModel_sync", + "segments": [ + { + "end": 51, + "start": 27, + "type": "FULL" + }, + { + "end": 51, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 45, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 48, + "start": 46, + "type": "REQUEST_EXECUTION" + }, + { + "end": 52, + "start": 49, + "type": "RESPONSE_HANDLING" + } + ], + "title": "retail_v2beta_generated_model_service_get_model_sync.py" + }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.retail_v2beta.ModelServiceAsyncClient", + "shortName": "ModelServiceAsyncClient" + }, + "fullName": "google.cloud.retail_v2beta.ModelServiceAsyncClient.list_models", + "method": { + "fullName": "google.cloud.retail.v2beta.ModelService.ListModels", + "service": { + "fullName": "google.cloud.retail.v2beta.ModelService", + "shortName": "ModelService" + }, + "shortName": "ListModels" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.retail_v2beta.types.ListModelsRequest" + }, + { + "name": "parent", + "type": "str" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.cloud.retail_v2beta.services.model_service.pagers.ListModelsAsyncPager", + "shortName": "list_models" + }, + "description": "Sample for ListModels", + "file": "retail_v2beta_generated_model_service_list_models_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "retail_v2beta_generated_ModelService_ListModels_async", + "segments": [ + { + "end": 52, + "start": 27, + "type": "FULL" + }, + { + "end": 52, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 45, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 48, + "start": 46, + "type": "REQUEST_EXECUTION" + }, + { + "end": 53, + "start": 49, + "type": "RESPONSE_HANDLING" + } + ], + "title": "retail_v2beta_generated_model_service_list_models_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.retail_v2beta.ModelServiceClient", + "shortName": "ModelServiceClient" + }, + "fullName": "google.cloud.retail_v2beta.ModelServiceClient.list_models", + "method": { + "fullName": "google.cloud.retail.v2beta.ModelService.ListModels", + "service": { + "fullName": "google.cloud.retail.v2beta.ModelService", + "shortName": "ModelService" + }, + "shortName": "ListModels" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.retail_v2beta.types.ListModelsRequest" + }, + { + "name": "parent", + "type": "str" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.cloud.retail_v2beta.services.model_service.pagers.ListModelsPager", + "shortName": "list_models" + }, + "description": "Sample for ListModels", + "file": "retail_v2beta_generated_model_service_list_models_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "retail_v2beta_generated_ModelService_ListModels_sync", + "segments": [ + { + "end": 52, + "start": 27, + "type": "FULL" + }, + { + "end": 52, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 45, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 48, + "start": 46, + "type": "REQUEST_EXECUTION" + }, + { + "end": 53, + "start": 49, + "type": "RESPONSE_HANDLING" + } + ], + "title": "retail_v2beta_generated_model_service_list_models_sync.py" + }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.retail_v2beta.ModelServiceAsyncClient", + "shortName": "ModelServiceAsyncClient" + }, + "fullName": "google.cloud.retail_v2beta.ModelServiceAsyncClient.pause_model", + "method": { + "fullName": "google.cloud.retail.v2beta.ModelService.PauseModel", + "service": { + "fullName": "google.cloud.retail.v2beta.ModelService", + "shortName": "ModelService" + }, + "shortName": "PauseModel" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.retail_v2beta.types.PauseModelRequest" + }, + { + "name": "name", + "type": "str" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.cloud.retail_v2beta.types.Model", + "shortName": "pause_model" + }, + "description": "Sample for PauseModel", + "file": "retail_v2beta_generated_model_service_pause_model_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "retail_v2beta_generated_ModelService_PauseModel_async", + "segments": [ + { + "end": 51, + "start": 27, + "type": "FULL" + }, + { + "end": 51, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 45, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 48, + "start": 46, + "type": "REQUEST_EXECUTION" + }, + { + "end": 52, + "start": 49, + "type": "RESPONSE_HANDLING" + } + ], + "title": "retail_v2beta_generated_model_service_pause_model_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.retail_v2beta.ModelServiceClient", + "shortName": "ModelServiceClient" + }, + "fullName": "google.cloud.retail_v2beta.ModelServiceClient.pause_model", + "method": { + "fullName": "google.cloud.retail.v2beta.ModelService.PauseModel", + "service": { + "fullName": "google.cloud.retail.v2beta.ModelService", + "shortName": "ModelService" + }, + "shortName": "PauseModel" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.retail_v2beta.types.PauseModelRequest" + }, + { + "name": "name", + "type": "str" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.cloud.retail_v2beta.types.Model", + "shortName": "pause_model" + }, + "description": "Sample for PauseModel", + "file": "retail_v2beta_generated_model_service_pause_model_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "retail_v2beta_generated_ModelService_PauseModel_sync", + "segments": [ + { + "end": 51, + "start": 27, + "type": "FULL" + }, + { + "end": 51, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 45, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 48, + "start": 46, + "type": "REQUEST_EXECUTION" + }, + { + "end": 52, + "start": 49, + "type": "RESPONSE_HANDLING" + } + ], + "title": "retail_v2beta_generated_model_service_pause_model_sync.py" + }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.retail_v2beta.ModelServiceAsyncClient", + "shortName": "ModelServiceAsyncClient" + }, + "fullName": "google.cloud.retail_v2beta.ModelServiceAsyncClient.resume_model", + "method": { + "fullName": "google.cloud.retail.v2beta.ModelService.ResumeModel", + "service": { + "fullName": "google.cloud.retail.v2beta.ModelService", + "shortName": "ModelService" + }, + "shortName": "ResumeModel" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.retail_v2beta.types.ResumeModelRequest" + }, + { + "name": "name", + "type": "str" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.cloud.retail_v2beta.types.Model", + "shortName": "resume_model" + }, + "description": "Sample for ResumeModel", + "file": "retail_v2beta_generated_model_service_resume_model_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "retail_v2beta_generated_ModelService_ResumeModel_async", + "segments": [ + { + "end": 51, + "start": 27, + "type": "FULL" + }, + { + "end": 51, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 45, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 48, + "start": 46, + "type": "REQUEST_EXECUTION" + }, + { + "end": 52, + "start": 49, + "type": "RESPONSE_HANDLING" + } + ], + "title": "retail_v2beta_generated_model_service_resume_model_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.retail_v2beta.ModelServiceClient", + "shortName": "ModelServiceClient" + }, + "fullName": "google.cloud.retail_v2beta.ModelServiceClient.resume_model", + "method": { + "fullName": "google.cloud.retail.v2beta.ModelService.ResumeModel", + "service": { + "fullName": "google.cloud.retail.v2beta.ModelService", + "shortName": "ModelService" + }, + "shortName": "ResumeModel" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.retail_v2beta.types.ResumeModelRequest" + }, + { + "name": "name", + "type": "str" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.cloud.retail_v2beta.types.Model", + "shortName": "resume_model" + }, + "description": "Sample for ResumeModel", + "file": "retail_v2beta_generated_model_service_resume_model_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "retail_v2beta_generated_ModelService_ResumeModel_sync", + "segments": [ + { + "end": 51, + "start": 27, + "type": "FULL" + }, + { + "end": 51, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 45, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 48, + "start": 46, + "type": "REQUEST_EXECUTION" + }, + { + "end": 52, + "start": 49, + "type": "RESPONSE_HANDLING" + } + ], + "title": "retail_v2beta_generated_model_service_resume_model_sync.py" + }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.retail_v2beta.ModelServiceAsyncClient", + "shortName": "ModelServiceAsyncClient" + }, + "fullName": "google.cloud.retail_v2beta.ModelServiceAsyncClient.tune_model", + "method": { + "fullName": "google.cloud.retail.v2beta.ModelService.TuneModel", + "service": { + "fullName": "google.cloud.retail.v2beta.ModelService", + "shortName": "ModelService" + }, + "shortName": "TuneModel" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.retail_v2beta.types.TuneModelRequest" + }, + { + "name": "name", + "type": "str" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.api_core.operation_async.AsyncOperation", + "shortName": "tune_model" + }, + "description": "Sample for TuneModel", + "file": "retail_v2beta_generated_model_service_tune_model_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "retail_v2beta_generated_ModelService_TuneModel_async", + "segments": [ + { + "end": 55, + "start": 27, + "type": "FULL" + }, + { + "end": 55, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 45, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 52, + "start": 46, + "type": "REQUEST_EXECUTION" + }, + { + "end": 56, + "start": 53, + "type": "RESPONSE_HANDLING" + } + ], + "title": "retail_v2beta_generated_model_service_tune_model_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.retail_v2beta.ModelServiceClient", + "shortName": "ModelServiceClient" + }, + "fullName": "google.cloud.retail_v2beta.ModelServiceClient.tune_model", + "method": { + "fullName": "google.cloud.retail.v2beta.ModelService.TuneModel", + "service": { + "fullName": "google.cloud.retail.v2beta.ModelService", + "shortName": "ModelService" + }, + "shortName": "TuneModel" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.retail_v2beta.types.TuneModelRequest" + }, + { + "name": "name", + "type": "str" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.api_core.operation.Operation", + "shortName": "tune_model" + }, + "description": "Sample for TuneModel", + "file": "retail_v2beta_generated_model_service_tune_model_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "retail_v2beta_generated_ModelService_TuneModel_sync", + "segments": [ + { + "end": 55, + "start": 27, + "type": "FULL" + }, + { + "end": 55, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 45, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 52, + "start": 46, + "type": "REQUEST_EXECUTION" + }, + { + "end": 56, + "start": 53, + "type": "RESPONSE_HANDLING" + } + ], + "title": "retail_v2beta_generated_model_service_tune_model_sync.py" + }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.retail_v2beta.ModelServiceAsyncClient", + "shortName": "ModelServiceAsyncClient" + }, + "fullName": "google.cloud.retail_v2beta.ModelServiceAsyncClient.update_model", + "method": { + "fullName": "google.cloud.retail.v2beta.ModelService.UpdateModel", + "service": { + "fullName": "google.cloud.retail.v2beta.ModelService", + "shortName": "ModelService" + }, + "shortName": "UpdateModel" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.retail_v2beta.types.UpdateModelRequest" + }, + { + "name": "model", + "type": "google.cloud.retail_v2beta.types.Model" + }, + { + "name": "update_mask", + "type": "google.protobuf.field_mask_pb2.FieldMask" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.cloud.retail_v2beta.types.Model", + "shortName": "update_model" + }, + "description": "Sample for UpdateModel", + "file": "retail_v2beta_generated_model_service_update_model_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "retail_v2beta_generated_ModelService_UpdateModel_async", + "segments": [ + { + "end": 56, + "start": 27, + "type": "FULL" + }, + { + "end": 56, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 50, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 53, + "start": 51, + "type": "REQUEST_EXECUTION" + }, + { + "end": 57, + "start": 54, + "type": "RESPONSE_HANDLING" + } + ], + "title": "retail_v2beta_generated_model_service_update_model_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.retail_v2beta.ModelServiceClient", + "shortName": "ModelServiceClient" + }, + "fullName": "google.cloud.retail_v2beta.ModelServiceClient.update_model", + "method": { + "fullName": "google.cloud.retail.v2beta.ModelService.UpdateModel", + "service": { + "fullName": "google.cloud.retail.v2beta.ModelService", + "shortName": "ModelService" + }, + "shortName": "UpdateModel" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.retail_v2beta.types.UpdateModelRequest" + }, + { + "name": "model", + "type": "google.cloud.retail_v2beta.types.Model" + }, + { + "name": "update_mask", + "type": "google.protobuf.field_mask_pb2.FieldMask" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.cloud.retail_v2beta.types.Model", + "shortName": "update_model" + }, + "description": "Sample for UpdateModel", + "file": "retail_v2beta_generated_model_service_update_model_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "retail_v2beta_generated_ModelService_UpdateModel_sync", + "segments": [ + { + "end": 56, + "start": 27, + "type": "FULL" + }, + { + "end": 56, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 50, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 53, + "start": 51, + "type": "REQUEST_EXECUTION" + }, + { + "end": 57, + "start": 54, + "type": "RESPONSE_HANDLING" + } + ], + "title": "retail_v2beta_generated_model_service_update_model_sync.py" + }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.retail_v2beta.PredictionServiceAsyncClient", + "shortName": "PredictionServiceAsyncClient" + }, + "fullName": "google.cloud.retail_v2beta.PredictionServiceAsyncClient.predict", + "method": { + "fullName": "google.cloud.retail.v2beta.PredictionService.Predict", + "service": { + "fullName": "google.cloud.retail.v2beta.PredictionService", + "shortName": "PredictionService" + }, + "shortName": "Predict" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.retail_v2beta.types.PredictRequest" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.cloud.retail_v2beta.types.PredictResponse", + "shortName": "predict" + }, + "description": "Sample for Predict", + "file": "retail_v2beta_generated_prediction_service_predict_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "retail_v2beta_generated_PredictionService_Predict_async", + "segments": [ + { + "end": 56, + "start": 27, + "type": "FULL" + }, + { + "end": 56, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 50, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 53, + "start": 51, + "type": "REQUEST_EXECUTION" + }, + { + "end": 57, + "start": 54, + "type": "RESPONSE_HANDLING" + } + ], + "title": "retail_v2beta_generated_prediction_service_predict_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.retail_v2beta.PredictionServiceClient", + "shortName": "PredictionServiceClient" + }, + "fullName": "google.cloud.retail_v2beta.PredictionServiceClient.predict", + "method": { + "fullName": "google.cloud.retail.v2beta.PredictionService.Predict", + "service": { + "fullName": "google.cloud.retail.v2beta.PredictionService", + "shortName": "PredictionService" + }, + "shortName": "Predict" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.retail_v2beta.types.PredictRequest" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.cloud.retail_v2beta.types.PredictResponse", + "shortName": "predict" + }, + "description": "Sample for Predict", + "file": "retail_v2beta_generated_prediction_service_predict_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "retail_v2beta_generated_PredictionService_Predict_sync", + "segments": [ + { + "end": 56, + "start": 27, + "type": "FULL" + }, + { + "end": 56, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 50, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 53, + "start": 51, + "type": "REQUEST_EXECUTION" + }, + { + "end": 57, + "start": 54, + "type": "RESPONSE_HANDLING" + } + ], + "title": "retail_v2beta_generated_prediction_service_predict_sync.py" + }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.retail_v2beta.ProductServiceAsyncClient", + "shortName": "ProductServiceAsyncClient" + }, + "fullName": "google.cloud.retail_v2beta.ProductServiceAsyncClient.add_fulfillment_places", + "method": { + "fullName": "google.cloud.retail.v2beta.ProductService.AddFulfillmentPlaces", + "service": { + "fullName": "google.cloud.retail.v2beta.ProductService", + "shortName": "ProductService" + }, + "shortName": "AddFulfillmentPlaces" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.retail_v2beta.types.AddFulfillmentPlacesRequest" + }, + { + "name": "product", + "type": "str" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.api_core.operation_async.AsyncOperation", + "shortName": "add_fulfillment_places" + }, + "description": "Sample for AddFulfillmentPlaces", + "file": "retail_v2beta_generated_product_service_add_fulfillment_places_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "retail_v2beta_generated_ProductService_AddFulfillmentPlaces_async", + "segments": [ + { + "end": 57, + "start": 27, + "type": "FULL" + }, + { + "end": 57, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 47, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 54, + "start": 48, + "type": "REQUEST_EXECUTION" + }, + { + "end": 58, + "start": 55, + "type": "RESPONSE_HANDLING" + } + ], + "title": "retail_v2beta_generated_product_service_add_fulfillment_places_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.retail_v2beta.ProductServiceClient", + "shortName": "ProductServiceClient" + }, + "fullName": "google.cloud.retail_v2beta.ProductServiceClient.add_fulfillment_places", + "method": { + "fullName": "google.cloud.retail.v2beta.ProductService.AddFulfillmentPlaces", + "service": { + "fullName": "google.cloud.retail.v2beta.ProductService", + "shortName": "ProductService" + }, + "shortName": "AddFulfillmentPlaces" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.retail_v2beta.types.AddFulfillmentPlacesRequest" + }, + { + "name": "product", + "type": "str" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.api_core.operation.Operation", + "shortName": "add_fulfillment_places" + }, + "description": "Sample for AddFulfillmentPlaces", + "file": "retail_v2beta_generated_product_service_add_fulfillment_places_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "retail_v2beta_generated_ProductService_AddFulfillmentPlaces_sync", + "segments": [ + { + "end": 57, + "start": 27, + "type": "FULL" + }, + { + "end": 57, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 47, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 54, + "start": 48, + "type": "REQUEST_EXECUTION" + }, + { + "end": 58, + "start": 55, + "type": "RESPONSE_HANDLING" + } + ], + "title": "retail_v2beta_generated_product_service_add_fulfillment_places_sync.py" + }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.retail_v2beta.ProductServiceAsyncClient", + "shortName": "ProductServiceAsyncClient" + }, + "fullName": "google.cloud.retail_v2beta.ProductServiceAsyncClient.add_local_inventories", + "method": { + "fullName": "google.cloud.retail.v2beta.ProductService.AddLocalInventories", + "service": { + "fullName": "google.cloud.retail.v2beta.ProductService", + "shortName": "ProductService" + }, + "shortName": "AddLocalInventories" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.retail_v2beta.types.AddLocalInventoriesRequest" + }, + { + "name": "product", + "type": "str" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.api_core.operation_async.AsyncOperation", + "shortName": "add_local_inventories" + }, + "description": "Sample for AddLocalInventories", + "file": "retail_v2beta_generated_product_service_add_local_inventories_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "retail_v2beta_generated_ProductService_AddLocalInventories_async", + "segments": [ + { + "end": 55, + "start": 27, + "type": "FULL" + }, + { + "end": 55, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 45, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 52, + "start": 46, + "type": "REQUEST_EXECUTION" + }, + { + "end": 56, + "start": 53, + "type": "RESPONSE_HANDLING" + } + ], + "title": "retail_v2beta_generated_product_service_add_local_inventories_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.retail_v2beta.ProductServiceClient", + "shortName": "ProductServiceClient" + }, + "fullName": "google.cloud.retail_v2beta.ProductServiceClient.add_local_inventories", + "method": { + "fullName": "google.cloud.retail.v2beta.ProductService.AddLocalInventories", + "service": { + "fullName": "google.cloud.retail.v2beta.ProductService", + "shortName": "ProductService" + }, + "shortName": "AddLocalInventories" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.retail_v2beta.types.AddLocalInventoriesRequest" }, { - "name": "update_mask", - "type": "google.protobuf.field_mask_pb2.FieldMask" + "name": "product", + "type": "str" }, { "name": "retry", @@ -4467,22 +5771,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.retail_v2beta.types.Model", - "shortName": "update_model" + "resultType": "google.api_core.operation.Operation", + "shortName": "add_local_inventories" }, - "description": "Sample for UpdateModel", - "file": "retail_v2beta_generated_model_service_update_model_sync.py", + "description": "Sample for AddLocalInventories", + "file": "retail_v2beta_generated_product_service_add_local_inventories_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "retail_v2beta_generated_ModelService_UpdateModel_sync", + "regionTag": "retail_v2beta_generated_ProductService_AddLocalInventories_sync", "segments": [ { - "end": 56, + "end": 55, "start": 27, "type": "FULL" }, { - "end": 56, + "end": 55, "start": 27, "type": "SHORT" }, @@ -4492,44 +5796,56 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 50, + "end": 45, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 53, - "start": 51, + "end": 52, + "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 57, - "start": 54, + "end": 56, + "start": 53, "type": "RESPONSE_HANDLING" } ], - "title": "retail_v2beta_generated_model_service_update_model_sync.py" + "title": "retail_v2beta_generated_product_service_add_local_inventories_sync.py" }, { "canonical": true, "clientMethod": { "async": true, "client": { - "fullName": "google.cloud.retail_v2beta.PredictionServiceAsyncClient", - "shortName": "PredictionServiceAsyncClient" + "fullName": "google.cloud.retail_v2beta.ProductServiceAsyncClient", + "shortName": "ProductServiceAsyncClient" }, - "fullName": "google.cloud.retail_v2beta.PredictionServiceAsyncClient.predict", + "fullName": "google.cloud.retail_v2beta.ProductServiceAsyncClient.create_product", "method": { - "fullName": "google.cloud.retail.v2beta.PredictionService.Predict", + "fullName": "google.cloud.retail.v2beta.ProductService.CreateProduct", "service": { - "fullName": "google.cloud.retail.v2beta.PredictionService", - "shortName": "PredictionService" + "fullName": "google.cloud.retail.v2beta.ProductService", + "shortName": "ProductService" }, - "shortName": "Predict" + "shortName": "CreateProduct" }, "parameters": [ { "name": "request", - "type": "google.cloud.retail_v2beta.types.PredictRequest" + "type": "google.cloud.retail_v2beta.types.CreateProductRequest" + }, + { + "name": "parent", + "type": "str" + }, + { + "name": "product", + "type": "google.cloud.retail_v2beta.types.Product" + }, + { + "name": "product_id", + "type": "str" }, { "name": "retry", @@ -4544,14 +5860,14 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.retail_v2beta.types.PredictResponse", - "shortName": "predict" + "resultType": "google.cloud.retail_v2beta.types.Product", + "shortName": "create_product" }, - "description": "Sample for Predict", - "file": "retail_v2beta_generated_prediction_service_predict_async.py", + "description": "Sample for CreateProduct", + "file": "retail_v2beta_generated_product_service_create_product_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "retail_v2beta_generated_PredictionService_Predict_async", + "regionTag": "retail_v2beta_generated_ProductService_CreateProduct_async", "segments": [ { "end": 56, @@ -4584,28 +5900,40 @@ "type": "RESPONSE_HANDLING" } ], - "title": "retail_v2beta_generated_prediction_service_predict_async.py" + "title": "retail_v2beta_generated_product_service_create_product_async.py" }, { "canonical": true, "clientMethod": { "client": { - "fullName": "google.cloud.retail_v2beta.PredictionServiceClient", - "shortName": "PredictionServiceClient" + "fullName": "google.cloud.retail_v2beta.ProductServiceClient", + "shortName": "ProductServiceClient" }, - "fullName": "google.cloud.retail_v2beta.PredictionServiceClient.predict", + "fullName": "google.cloud.retail_v2beta.ProductServiceClient.create_product", "method": { - "fullName": "google.cloud.retail.v2beta.PredictionService.Predict", + "fullName": "google.cloud.retail.v2beta.ProductService.CreateProduct", "service": { - "fullName": "google.cloud.retail.v2beta.PredictionService", - "shortName": "PredictionService" + "fullName": "google.cloud.retail.v2beta.ProductService", + "shortName": "ProductService" }, - "shortName": "Predict" + "shortName": "CreateProduct" }, "parameters": [ { "name": "request", - "type": "google.cloud.retail_v2beta.types.PredictRequest" + "type": "google.cloud.retail_v2beta.types.CreateProductRequest" + }, + { + "name": "parent", + "type": "str" + }, + { + "name": "product", + "type": "google.cloud.retail_v2beta.types.Product" + }, + { + "name": "product_id", + "type": "str" }, { "name": "retry", @@ -4620,14 +5948,14 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.retail_v2beta.types.PredictResponse", - "shortName": "predict" + "resultType": "google.cloud.retail_v2beta.types.Product", + "shortName": "create_product" }, - "description": "Sample for Predict", - "file": "retail_v2beta_generated_prediction_service_predict_sync.py", + "description": "Sample for CreateProduct", + "file": "retail_v2beta_generated_product_service_create_product_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "retail_v2beta_generated_PredictionService_Predict_sync", + "regionTag": "retail_v2beta_generated_ProductService_CreateProduct_sync", "segments": [ { "end": 56, @@ -4660,7 +5988,7 @@ "type": "RESPONSE_HANDLING" } ], - "title": "retail_v2beta_generated_prediction_service_predict_sync.py" + "title": "retail_v2beta_generated_product_service_create_product_sync.py" }, { "canonical": true, @@ -4670,22 +5998,22 @@ "fullName": "google.cloud.retail_v2beta.ProductServiceAsyncClient", "shortName": "ProductServiceAsyncClient" }, - "fullName": "google.cloud.retail_v2beta.ProductServiceAsyncClient.add_fulfillment_places", + "fullName": "google.cloud.retail_v2beta.ProductServiceAsyncClient.delete_product", "method": { - "fullName": "google.cloud.retail.v2beta.ProductService.AddFulfillmentPlaces", + "fullName": "google.cloud.retail.v2beta.ProductService.DeleteProduct", "service": { "fullName": "google.cloud.retail.v2beta.ProductService", "shortName": "ProductService" }, - "shortName": "AddFulfillmentPlaces" + "shortName": "DeleteProduct" }, "parameters": [ { "name": "request", - "type": "google.cloud.retail_v2beta.types.AddFulfillmentPlacesRequest" + "type": "google.cloud.retail_v2beta.types.DeleteProductRequest" }, { - "name": "product", + "name": "name", "type": "str" }, { @@ -4701,22 +6029,21 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.api_core.operation_async.AsyncOperation", - "shortName": "add_fulfillment_places" + "shortName": "delete_product" }, - "description": "Sample for AddFulfillmentPlaces", - "file": "retail_v2beta_generated_product_service_add_fulfillment_places_async.py", + "description": "Sample for DeleteProduct", + "file": "retail_v2beta_generated_product_service_delete_product_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "retail_v2beta_generated_ProductService_AddFulfillmentPlaces_async", + "regionTag": "retail_v2beta_generated_ProductService_DeleteProduct_async", "segments": [ { - "end": 57, + "end": 49, "start": 27, "type": "FULL" }, { - "end": 57, + "end": 49, "start": 27, "type": "SHORT" }, @@ -4726,22 +6053,20 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 47, + "end": 45, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 54, - "start": 48, + "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 58, - "start": 55, + "end": 50, "type": "RESPONSE_HANDLING" } ], - "title": "retail_v2beta_generated_product_service_add_fulfillment_places_async.py" + "title": "retail_v2beta_generated_product_service_delete_product_async.py" }, { "canonical": true, @@ -4750,22 +6075,22 @@ "fullName": "google.cloud.retail_v2beta.ProductServiceClient", "shortName": "ProductServiceClient" }, - "fullName": "google.cloud.retail_v2beta.ProductServiceClient.add_fulfillment_places", + "fullName": "google.cloud.retail_v2beta.ProductServiceClient.delete_product", "method": { - "fullName": "google.cloud.retail.v2beta.ProductService.AddFulfillmentPlaces", + "fullName": "google.cloud.retail.v2beta.ProductService.DeleteProduct", "service": { "fullName": "google.cloud.retail.v2beta.ProductService", "shortName": "ProductService" }, - "shortName": "AddFulfillmentPlaces" + "shortName": "DeleteProduct" }, "parameters": [ { "name": "request", - "type": "google.cloud.retail_v2beta.types.AddFulfillmentPlacesRequest" + "type": "google.cloud.retail_v2beta.types.DeleteProductRequest" }, { - "name": "product", + "name": "name", "type": "str" }, { @@ -4781,22 +6106,21 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.api_core.operation.Operation", - "shortName": "add_fulfillment_places" + "shortName": "delete_product" }, - "description": "Sample for AddFulfillmentPlaces", - "file": "retail_v2beta_generated_product_service_add_fulfillment_places_sync.py", + "description": "Sample for DeleteProduct", + "file": "retail_v2beta_generated_product_service_delete_product_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "retail_v2beta_generated_ProductService_AddFulfillmentPlaces_sync", + "regionTag": "retail_v2beta_generated_ProductService_DeleteProduct_sync", "segments": [ { - "end": 57, + "end": 49, "start": 27, "type": "FULL" }, { - "end": 57, + "end": 49, "start": 27, "type": "SHORT" }, @@ -4806,22 +6130,20 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 47, + "end": 45, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 54, - "start": 48, + "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 58, - "start": 55, + "end": 50, "type": "RESPONSE_HANDLING" } ], - "title": "retail_v2beta_generated_product_service_add_fulfillment_places_sync.py" + "title": "retail_v2beta_generated_product_service_delete_product_sync.py" }, { "canonical": true, @@ -4831,23 +6153,19 @@ "fullName": "google.cloud.retail_v2beta.ProductServiceAsyncClient", "shortName": "ProductServiceAsyncClient" }, - "fullName": "google.cloud.retail_v2beta.ProductServiceAsyncClient.add_local_inventories", + "fullName": "google.cloud.retail_v2beta.ProductServiceAsyncClient.export_products", "method": { - "fullName": "google.cloud.retail.v2beta.ProductService.AddLocalInventories", + "fullName": "google.cloud.retail.v2beta.ProductService.ExportProducts", "service": { "fullName": "google.cloud.retail.v2beta.ProductService", "shortName": "ProductService" }, - "shortName": "AddLocalInventories" + "shortName": "ExportProducts" }, "parameters": [ { "name": "request", - "type": "google.cloud.retail_v2beta.types.AddLocalInventoriesRequest" - }, - { - "name": "product", - "type": "str" + "type": "google.cloud.retail_v2beta.types.ExportProductsRequest" }, { "name": "retry", @@ -4863,21 +6181,21 @@ } ], "resultType": "google.api_core.operation_async.AsyncOperation", - "shortName": "add_local_inventories" + "shortName": "export_products" }, - "description": "Sample for AddLocalInventories", - "file": "retail_v2beta_generated_product_service_add_local_inventories_async.py", + "description": "Sample for ExportProducts", + "file": "retail_v2beta_generated_product_service_export_products_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "retail_v2beta_generated_ProductService_AddLocalInventories_async", + "regionTag": "retail_v2beta_generated_ProductService_ExportProducts_async", "segments": [ { - "end": 55, + "end": 59, "start": 27, "type": "FULL" }, { - "end": 55, + "end": 59, "start": 27, "type": "SHORT" }, @@ -4887,22 +6205,22 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 45, + "end": 49, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 52, - "start": 46, + "end": 56, + "start": 50, "type": "REQUEST_EXECUTION" }, { - "end": 56, - "start": 53, + "end": 60, + "start": 57, "type": "RESPONSE_HANDLING" } ], - "title": "retail_v2beta_generated_product_service_add_local_inventories_async.py" + "title": "retail_v2beta_generated_product_service_export_products_async.py" }, { "canonical": true, @@ -4911,23 +6229,19 @@ "fullName": "google.cloud.retail_v2beta.ProductServiceClient", "shortName": "ProductServiceClient" }, - "fullName": "google.cloud.retail_v2beta.ProductServiceClient.add_local_inventories", + "fullName": "google.cloud.retail_v2beta.ProductServiceClient.export_products", "method": { - "fullName": "google.cloud.retail.v2beta.ProductService.AddLocalInventories", + "fullName": "google.cloud.retail.v2beta.ProductService.ExportProducts", "service": { "fullName": "google.cloud.retail.v2beta.ProductService", "shortName": "ProductService" }, - "shortName": "AddLocalInventories" + "shortName": "ExportProducts" }, "parameters": [ { "name": "request", - "type": "google.cloud.retail_v2beta.types.AddLocalInventoriesRequest" - }, - { - "name": "product", - "type": "str" + "type": "google.cloud.retail_v2beta.types.ExportProductsRequest" }, { "name": "retry", @@ -4943,21 +6257,21 @@ } ], "resultType": "google.api_core.operation.Operation", - "shortName": "add_local_inventories" + "shortName": "export_products" }, - "description": "Sample for AddLocalInventories", - "file": "retail_v2beta_generated_product_service_add_local_inventories_sync.py", + "description": "Sample for ExportProducts", + "file": "retail_v2beta_generated_product_service_export_products_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "retail_v2beta_generated_ProductService_AddLocalInventories_sync", + "regionTag": "retail_v2beta_generated_ProductService_ExportProducts_sync", "segments": [ { - "end": 55, + "end": 59, "start": 27, "type": "FULL" }, { - "end": 55, + "end": 59, "start": 27, "type": "SHORT" }, @@ -4967,22 +6281,22 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 45, + "end": 49, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 52, - "start": 46, + "end": 56, + "start": 50, "type": "REQUEST_EXECUTION" }, { - "end": 56, - "start": 53, + "end": 60, + "start": 57, "type": "RESPONSE_HANDLING" } ], - "title": "retail_v2beta_generated_product_service_add_local_inventories_sync.py" + "title": "retail_v2beta_generated_product_service_export_products_sync.py" }, { "canonical": true, @@ -4992,30 +6306,22 @@ "fullName": "google.cloud.retail_v2beta.ProductServiceAsyncClient", "shortName": "ProductServiceAsyncClient" }, - "fullName": "google.cloud.retail_v2beta.ProductServiceAsyncClient.create_product", + "fullName": "google.cloud.retail_v2beta.ProductServiceAsyncClient.get_product", "method": { - "fullName": "google.cloud.retail.v2beta.ProductService.CreateProduct", + "fullName": "google.cloud.retail.v2beta.ProductService.GetProduct", "service": { "fullName": "google.cloud.retail.v2beta.ProductService", "shortName": "ProductService" }, - "shortName": "CreateProduct" + "shortName": "GetProduct" }, "parameters": [ { "name": "request", - "type": "google.cloud.retail_v2beta.types.CreateProductRequest" - }, - { - "name": "parent", - "type": "str" - }, - { - "name": "product", - "type": "google.cloud.retail_v2beta.types.Product" + "type": "google.cloud.retail_v2beta.types.GetProductRequest" }, { - "name": "product_id", + "name": "name", "type": "str" }, { @@ -5032,21 +6338,21 @@ } ], "resultType": "google.cloud.retail_v2beta.types.Product", - "shortName": "create_product" - }, - "description": "Sample for CreateProduct", - "file": "retail_v2beta_generated_product_service_create_product_async.py", + "shortName": "get_product" + }, + "description": "Sample for GetProduct", + "file": "retail_v2beta_generated_product_service_get_product_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "retail_v2beta_generated_ProductService_CreateProduct_async", + "regionTag": "retail_v2beta_generated_ProductService_GetProduct_async", "segments": [ { - "end": 56, + "end": 51, "start": 27, "type": "FULL" }, { - "end": 56, + "end": 51, "start": 27, "type": "SHORT" }, @@ -5056,22 +6362,22 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 50, + "end": 45, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 53, - "start": 51, + "end": 48, + "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 57, - "start": 54, + "end": 52, + "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "retail_v2beta_generated_product_service_create_product_async.py" + "title": "retail_v2beta_generated_product_service_get_product_async.py" }, { "canonical": true, @@ -5080,30 +6386,22 @@ "fullName": "google.cloud.retail_v2beta.ProductServiceClient", "shortName": "ProductServiceClient" }, - "fullName": "google.cloud.retail_v2beta.ProductServiceClient.create_product", + "fullName": "google.cloud.retail_v2beta.ProductServiceClient.get_product", "method": { - "fullName": "google.cloud.retail.v2beta.ProductService.CreateProduct", + "fullName": "google.cloud.retail.v2beta.ProductService.GetProduct", "service": { "fullName": "google.cloud.retail.v2beta.ProductService", "shortName": "ProductService" }, - "shortName": "CreateProduct" + "shortName": "GetProduct" }, "parameters": [ { "name": "request", - "type": "google.cloud.retail_v2beta.types.CreateProductRequest" - }, - { - "name": "parent", - "type": "str" - }, - { - "name": "product", - "type": "google.cloud.retail_v2beta.types.Product" + "type": "google.cloud.retail_v2beta.types.GetProductRequest" }, { - "name": "product_id", + "name": "name", "type": "str" }, { @@ -5120,21 +6418,21 @@ } ], "resultType": "google.cloud.retail_v2beta.types.Product", - "shortName": "create_product" + "shortName": "get_product" }, - "description": "Sample for CreateProduct", - "file": "retail_v2beta_generated_product_service_create_product_sync.py", + "description": "Sample for GetProduct", + "file": "retail_v2beta_generated_product_service_get_product_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "retail_v2beta_generated_ProductService_CreateProduct_sync", + "regionTag": "retail_v2beta_generated_ProductService_GetProduct_sync", "segments": [ { - "end": 56, + "end": 51, "start": 27, "type": "FULL" }, { - "end": 56, + "end": 51, "start": 27, "type": "SHORT" }, @@ -5144,22 +6442,22 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 50, + "end": 45, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 53, - "start": 51, + "end": 48, + "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 57, - "start": 54, + "end": 52, + "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "retail_v2beta_generated_product_service_create_product_sync.py" + "title": "retail_v2beta_generated_product_service_get_product_sync.py" }, { "canonical": true, @@ -5169,23 +6467,19 @@ "fullName": "google.cloud.retail_v2beta.ProductServiceAsyncClient", "shortName": "ProductServiceAsyncClient" }, - "fullName": "google.cloud.retail_v2beta.ProductServiceAsyncClient.delete_product", + "fullName": "google.cloud.retail_v2beta.ProductServiceAsyncClient.import_products", "method": { - "fullName": "google.cloud.retail.v2beta.ProductService.DeleteProduct", + "fullName": "google.cloud.retail.v2beta.ProductService.ImportProducts", "service": { "fullName": "google.cloud.retail.v2beta.ProductService", "shortName": "ProductService" }, - "shortName": "DeleteProduct" + "shortName": "ImportProducts" }, "parameters": [ { "name": "request", - "type": "google.cloud.retail_v2beta.types.DeleteProductRequest" - }, - { - "name": "name", - "type": "str" + "type": "google.cloud.retail_v2beta.types.ImportProductsRequest" }, { "name": "retry", @@ -5200,21 +6494,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "shortName": "delete_product" + "resultType": "google.api_core.operation_async.AsyncOperation", + "shortName": "import_products" }, - "description": "Sample for DeleteProduct", - "file": "retail_v2beta_generated_product_service_delete_product_async.py", + "description": "Sample for ImportProducts", + "file": "retail_v2beta_generated_product_service_import_products_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "retail_v2beta_generated_ProductService_DeleteProduct_async", + "regionTag": "retail_v2beta_generated_ProductService_ImportProducts_async", "segments": [ { - "end": 49, + "end": 59, "start": 27, "type": "FULL" }, { - "end": 49, + "end": 59, "start": 27, "type": "SHORT" }, @@ -5224,20 +6519,22 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 45, + "end": 49, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "start": 46, + "end": 56, + "start": 50, "type": "REQUEST_EXECUTION" }, { - "end": 50, + "end": 60, + "start": 57, "type": "RESPONSE_HANDLING" } ], - "title": "retail_v2beta_generated_product_service_delete_product_async.py" + "title": "retail_v2beta_generated_product_service_import_products_async.py" }, { "canonical": true, @@ -5246,23 +6543,19 @@ "fullName": "google.cloud.retail_v2beta.ProductServiceClient", "shortName": "ProductServiceClient" }, - "fullName": "google.cloud.retail_v2beta.ProductServiceClient.delete_product", + "fullName": "google.cloud.retail_v2beta.ProductServiceClient.import_products", "method": { - "fullName": "google.cloud.retail.v2beta.ProductService.DeleteProduct", + "fullName": "google.cloud.retail.v2beta.ProductService.ImportProducts", "service": { "fullName": "google.cloud.retail.v2beta.ProductService", "shortName": "ProductService" }, - "shortName": "DeleteProduct" + "shortName": "ImportProducts" }, "parameters": [ { "name": "request", - "type": "google.cloud.retail_v2beta.types.DeleteProductRequest" - }, - { - "name": "name", - "type": "str" + "type": "google.cloud.retail_v2beta.types.ImportProductsRequest" }, { "name": "retry", @@ -5277,21 +6570,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "shortName": "delete_product" + "resultType": "google.api_core.operation.Operation", + "shortName": "import_products" }, - "description": "Sample for DeleteProduct", - "file": "retail_v2beta_generated_product_service_delete_product_sync.py", + "description": "Sample for ImportProducts", + "file": "retail_v2beta_generated_product_service_import_products_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "retail_v2beta_generated_ProductService_DeleteProduct_sync", + "regionTag": "retail_v2beta_generated_ProductService_ImportProducts_sync", "segments": [ { - "end": 49, + "end": 59, "start": 27, "type": "FULL" }, { - "end": 49, + "end": 59, "start": 27, "type": "SHORT" }, @@ -5301,20 +6595,22 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 45, + "end": 49, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "start": 46, + "end": 56, + "start": 50, "type": "REQUEST_EXECUTION" }, { - "end": 50, + "end": 60, + "start": 57, "type": "RESPONSE_HANDLING" } ], - "title": "retail_v2beta_generated_product_service_delete_product_sync.py" + "title": "retail_v2beta_generated_product_service_import_products_sync.py" }, { "canonical": true, @@ -5324,22 +6620,22 @@ "fullName": "google.cloud.retail_v2beta.ProductServiceAsyncClient", "shortName": "ProductServiceAsyncClient" }, - "fullName": "google.cloud.retail_v2beta.ProductServiceAsyncClient.get_product", + "fullName": "google.cloud.retail_v2beta.ProductServiceAsyncClient.list_products", "method": { - "fullName": "google.cloud.retail.v2beta.ProductService.GetProduct", + "fullName": "google.cloud.retail.v2beta.ProductService.ListProducts", "service": { "fullName": "google.cloud.retail.v2beta.ProductService", "shortName": "ProductService" }, - "shortName": "GetProduct" + "shortName": "ListProducts" }, "parameters": [ { "name": "request", - "type": "google.cloud.retail_v2beta.types.GetProductRequest" + "type": "google.cloud.retail_v2beta.types.ListProductsRequest" }, { - "name": "name", + "name": "parent", "type": "str" }, { @@ -5355,22 +6651,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.retail_v2beta.types.Product", - "shortName": "get_product" + "resultType": "google.cloud.retail_v2beta.services.product_service.pagers.ListProductsAsyncPager", + "shortName": "list_products" }, - "description": "Sample for GetProduct", - "file": "retail_v2beta_generated_product_service_get_product_async.py", + "description": "Sample for ListProducts", + "file": "retail_v2beta_generated_product_service_list_products_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "retail_v2beta_generated_ProductService_GetProduct_async", + "regionTag": "retail_v2beta_generated_ProductService_ListProducts_async", "segments": [ { - "end": 51, + "end": 52, "start": 27, "type": "FULL" }, { - "end": 51, + "end": 52, "start": 27, "type": "SHORT" }, @@ -5390,12 +6686,12 @@ "type": "REQUEST_EXECUTION" }, { - "end": 52, + "end": 53, "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "retail_v2beta_generated_product_service_get_product_async.py" + "title": "retail_v2beta_generated_product_service_list_products_async.py" }, { "canonical": true, @@ -5404,22 +6700,22 @@ "fullName": "google.cloud.retail_v2beta.ProductServiceClient", "shortName": "ProductServiceClient" }, - "fullName": "google.cloud.retail_v2beta.ProductServiceClient.get_product", + "fullName": "google.cloud.retail_v2beta.ProductServiceClient.list_products", "method": { - "fullName": "google.cloud.retail.v2beta.ProductService.GetProduct", + "fullName": "google.cloud.retail.v2beta.ProductService.ListProducts", "service": { "fullName": "google.cloud.retail.v2beta.ProductService", "shortName": "ProductService" }, - "shortName": "GetProduct" + "shortName": "ListProducts" }, "parameters": [ { "name": "request", - "type": "google.cloud.retail_v2beta.types.GetProductRequest" + "type": "google.cloud.retail_v2beta.types.ListProductsRequest" }, { - "name": "name", + "name": "parent", "type": "str" }, { @@ -5435,22 +6731,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.retail_v2beta.types.Product", - "shortName": "get_product" + "resultType": "google.cloud.retail_v2beta.services.product_service.pagers.ListProductsPager", + "shortName": "list_products" }, - "description": "Sample for GetProduct", - "file": "retail_v2beta_generated_product_service_get_product_sync.py", + "description": "Sample for ListProducts", + "file": "retail_v2beta_generated_product_service_list_products_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "retail_v2beta_generated_ProductService_GetProduct_sync", + "regionTag": "retail_v2beta_generated_ProductService_ListProducts_sync", "segments": [ { - "end": 51, + "end": 52, "start": 27, "type": "FULL" }, { - "end": 51, + "end": 52, "start": 27, "type": "SHORT" }, @@ -5470,12 +6766,12 @@ "type": "REQUEST_EXECUTION" }, { - "end": 52, + "end": 53, "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "retail_v2beta_generated_product_service_get_product_sync.py" + "title": "retail_v2beta_generated_product_service_list_products_sync.py" }, { "canonical": true, @@ -5485,19 +6781,19 @@ "fullName": "google.cloud.retail_v2beta.ProductServiceAsyncClient", "shortName": "ProductServiceAsyncClient" }, - "fullName": "google.cloud.retail_v2beta.ProductServiceAsyncClient.import_products", + "fullName": "google.cloud.retail_v2beta.ProductServiceAsyncClient.purge_products", "method": { - "fullName": "google.cloud.retail.v2beta.ProductService.ImportProducts", + "fullName": "google.cloud.retail.v2beta.ProductService.PurgeProducts", "service": { "fullName": "google.cloud.retail.v2beta.ProductService", "shortName": "ProductService" }, - "shortName": "ImportProducts" + "shortName": "PurgeProducts" }, "parameters": [ { "name": "request", - "type": "google.cloud.retail_v2beta.types.ImportProductsRequest" + "type": "google.cloud.retail_v2beta.types.PurgeProductsRequest" }, { "name": "retry", @@ -5513,21 +6809,21 @@ } ], "resultType": "google.api_core.operation_async.AsyncOperation", - "shortName": "import_products" + "shortName": "purge_products" }, - "description": "Sample for ImportProducts", - "file": "retail_v2beta_generated_product_service_import_products_async.py", + "description": "Sample for PurgeProducts", + "file": "retail_v2beta_generated_product_service_purge_products_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "retail_v2beta_generated_ProductService_ImportProducts_async", + "regionTag": "retail_v2beta_generated_ProductService_PurgeProducts_async", "segments": [ { - "end": 59, + "end": 56, "start": 27, "type": "FULL" }, { - "end": 59, + "end": 56, "start": 27, "type": "SHORT" }, @@ -5537,22 +6833,22 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 49, + "end": 46, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 56, - "start": 50, + "end": 53, + "start": 47, "type": "REQUEST_EXECUTION" }, { - "end": 60, - "start": 57, + "end": 57, + "start": 54, "type": "RESPONSE_HANDLING" } ], - "title": "retail_v2beta_generated_product_service_import_products_async.py" + "title": "retail_v2beta_generated_product_service_purge_products_async.py" }, { "canonical": true, @@ -5561,19 +6857,19 @@ "fullName": "google.cloud.retail_v2beta.ProductServiceClient", "shortName": "ProductServiceClient" }, - "fullName": "google.cloud.retail_v2beta.ProductServiceClient.import_products", + "fullName": "google.cloud.retail_v2beta.ProductServiceClient.purge_products", "method": { - "fullName": "google.cloud.retail.v2beta.ProductService.ImportProducts", + "fullName": "google.cloud.retail.v2beta.ProductService.PurgeProducts", "service": { "fullName": "google.cloud.retail.v2beta.ProductService", "shortName": "ProductService" }, - "shortName": "ImportProducts" + "shortName": "PurgeProducts" }, "parameters": [ { "name": "request", - "type": "google.cloud.retail_v2beta.types.ImportProductsRequest" + "type": "google.cloud.retail_v2beta.types.PurgeProductsRequest" }, { "name": "retry", @@ -5589,21 +6885,21 @@ } ], "resultType": "google.api_core.operation.Operation", - "shortName": "import_products" + "shortName": "purge_products" }, - "description": "Sample for ImportProducts", - "file": "retail_v2beta_generated_product_service_import_products_sync.py", + "description": "Sample for PurgeProducts", + "file": "retail_v2beta_generated_product_service_purge_products_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "retail_v2beta_generated_ProductService_ImportProducts_sync", + "regionTag": "retail_v2beta_generated_ProductService_PurgeProducts_sync", "segments": [ { - "end": 59, + "end": 56, "start": 27, "type": "FULL" }, { - "end": 59, + "end": 56, "start": 27, "type": "SHORT" }, @@ -5613,22 +6909,22 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 49, + "end": 46, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 56, - "start": 50, + "end": 53, + "start": 47, "type": "REQUEST_EXECUTION" }, { - "end": 60, - "start": 57, + "end": 57, + "start": 54, "type": "RESPONSE_HANDLING" } ], - "title": "retail_v2beta_generated_product_service_import_products_sync.py" + "title": "retail_v2beta_generated_product_service_purge_products_sync.py" }, { "canonical": true, @@ -5638,22 +6934,22 @@ "fullName": "google.cloud.retail_v2beta.ProductServiceAsyncClient", "shortName": "ProductServiceAsyncClient" }, - "fullName": "google.cloud.retail_v2beta.ProductServiceAsyncClient.list_products", + "fullName": "google.cloud.retail_v2beta.ProductServiceAsyncClient.remove_fulfillment_places", "method": { - "fullName": "google.cloud.retail.v2beta.ProductService.ListProducts", + "fullName": "google.cloud.retail.v2beta.ProductService.RemoveFulfillmentPlaces", "service": { "fullName": "google.cloud.retail.v2beta.ProductService", "shortName": "ProductService" }, - "shortName": "ListProducts" + "shortName": "RemoveFulfillmentPlaces" }, "parameters": [ { "name": "request", - "type": "google.cloud.retail_v2beta.types.ListProductsRequest" + "type": "google.cloud.retail_v2beta.types.RemoveFulfillmentPlacesRequest" }, { - "name": "parent", + "name": "product", "type": "str" }, { @@ -5669,22 +6965,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.retail_v2beta.services.product_service.pagers.ListProductsAsyncPager", - "shortName": "list_products" + "resultType": "google.api_core.operation_async.AsyncOperation", + "shortName": "remove_fulfillment_places" }, - "description": "Sample for ListProducts", - "file": "retail_v2beta_generated_product_service_list_products_async.py", + "description": "Sample for RemoveFulfillmentPlaces", + "file": "retail_v2beta_generated_product_service_remove_fulfillment_places_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "retail_v2beta_generated_ProductService_ListProducts_async", + "regionTag": "retail_v2beta_generated_ProductService_RemoveFulfillmentPlaces_async", "segments": [ { - "end": 52, + "end": 57, "start": 27, "type": "FULL" }, { - "end": 52, + "end": 57, "start": 27, "type": "SHORT" }, @@ -5694,22 +6990,22 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 45, + "end": 47, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 48, - "start": 46, + "end": 54, + "start": 48, "type": "REQUEST_EXECUTION" }, { - "end": 53, - "start": 49, + "end": 58, + "start": 55, "type": "RESPONSE_HANDLING" } ], - "title": "retail_v2beta_generated_product_service_list_products_async.py" + "title": "retail_v2beta_generated_product_service_remove_fulfillment_places_async.py" }, { "canonical": true, @@ -5718,22 +7014,22 @@ "fullName": "google.cloud.retail_v2beta.ProductServiceClient", "shortName": "ProductServiceClient" }, - "fullName": "google.cloud.retail_v2beta.ProductServiceClient.list_products", + "fullName": "google.cloud.retail_v2beta.ProductServiceClient.remove_fulfillment_places", "method": { - "fullName": "google.cloud.retail.v2beta.ProductService.ListProducts", + "fullName": "google.cloud.retail.v2beta.ProductService.RemoveFulfillmentPlaces", "service": { "fullName": "google.cloud.retail.v2beta.ProductService", "shortName": "ProductService" }, - "shortName": "ListProducts" + "shortName": "RemoveFulfillmentPlaces" }, "parameters": [ { "name": "request", - "type": "google.cloud.retail_v2beta.types.ListProductsRequest" + "type": "google.cloud.retail_v2beta.types.RemoveFulfillmentPlacesRequest" }, { - "name": "parent", + "name": "product", "type": "str" }, { @@ -5749,22 +7045,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.retail_v2beta.services.product_service.pagers.ListProductsPager", - "shortName": "list_products" + "resultType": "google.api_core.operation.Operation", + "shortName": "remove_fulfillment_places" }, - "description": "Sample for ListProducts", - "file": "retail_v2beta_generated_product_service_list_products_sync.py", + "description": "Sample for RemoveFulfillmentPlaces", + "file": "retail_v2beta_generated_product_service_remove_fulfillment_places_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "retail_v2beta_generated_ProductService_ListProducts_sync", + "regionTag": "retail_v2beta_generated_ProductService_RemoveFulfillmentPlaces_sync", "segments": [ { - "end": 52, + "end": 57, "start": 27, "type": "FULL" }, { - "end": 52, + "end": 57, "start": 27, "type": "SHORT" }, @@ -5774,22 +7070,22 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 45, + "end": 47, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 48, - "start": 46, + "end": 54, + "start": 48, "type": "REQUEST_EXECUTION" }, { - "end": 53, - "start": 49, + "end": 58, + "start": 55, "type": "RESPONSE_HANDLING" } ], - "title": "retail_v2beta_generated_product_service_list_products_sync.py" + "title": "retail_v2beta_generated_product_service_remove_fulfillment_places_sync.py" }, { "canonical": true, @@ -5799,19 +7095,23 @@ "fullName": "google.cloud.retail_v2beta.ProductServiceAsyncClient", "shortName": "ProductServiceAsyncClient" }, - "fullName": "google.cloud.retail_v2beta.ProductServiceAsyncClient.purge_products", + "fullName": "google.cloud.retail_v2beta.ProductServiceAsyncClient.remove_local_inventories", "method": { - "fullName": "google.cloud.retail.v2beta.ProductService.PurgeProducts", + "fullName": "google.cloud.retail.v2beta.ProductService.RemoveLocalInventories", "service": { "fullName": "google.cloud.retail.v2beta.ProductService", "shortName": "ProductService" }, - "shortName": "PurgeProducts" + "shortName": "RemoveLocalInventories" }, "parameters": [ { "name": "request", - "type": "google.cloud.retail_v2beta.types.PurgeProductsRequest" + "type": "google.cloud.retail_v2beta.types.RemoveLocalInventoriesRequest" + }, + { + "name": "product", + "type": "str" }, { "name": "retry", @@ -5827,13 +7127,13 @@ } ], "resultType": "google.api_core.operation_async.AsyncOperation", - "shortName": "purge_products" + "shortName": "remove_local_inventories" }, - "description": "Sample for PurgeProducts", - "file": "retail_v2beta_generated_product_service_purge_products_async.py", + "description": "Sample for RemoveLocalInventories", + "file": "retail_v2beta_generated_product_service_remove_local_inventories_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "retail_v2beta_generated_ProductService_PurgeProducts_async", + "regionTag": "retail_v2beta_generated_ProductService_RemoveLocalInventories_async", "segments": [ { "end": 56, @@ -5866,7 +7166,7 @@ "type": "RESPONSE_HANDLING" } ], - "title": "retail_v2beta_generated_product_service_purge_products_async.py" + "title": "retail_v2beta_generated_product_service_remove_local_inventories_async.py" }, { "canonical": true, @@ -5875,19 +7175,23 @@ "fullName": "google.cloud.retail_v2beta.ProductServiceClient", "shortName": "ProductServiceClient" }, - "fullName": "google.cloud.retail_v2beta.ProductServiceClient.purge_products", + "fullName": "google.cloud.retail_v2beta.ProductServiceClient.remove_local_inventories", "method": { - "fullName": "google.cloud.retail.v2beta.ProductService.PurgeProducts", + "fullName": "google.cloud.retail.v2beta.ProductService.RemoveLocalInventories", "service": { "fullName": "google.cloud.retail.v2beta.ProductService", "shortName": "ProductService" }, - "shortName": "PurgeProducts" + "shortName": "RemoveLocalInventories" }, "parameters": [ { "name": "request", - "type": "google.cloud.retail_v2beta.types.PurgeProductsRequest" + "type": "google.cloud.retail_v2beta.types.RemoveLocalInventoriesRequest" + }, + { + "name": "product", + "type": "str" }, { "name": "retry", @@ -5903,13 +7207,13 @@ } ], "resultType": "google.api_core.operation.Operation", - "shortName": "purge_products" + "shortName": "remove_local_inventories" }, - "description": "Sample for PurgeProducts", - "file": "retail_v2beta_generated_product_service_purge_products_sync.py", + "description": "Sample for RemoveLocalInventories", + "file": "retail_v2beta_generated_product_service_remove_local_inventories_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "retail_v2beta_generated_ProductService_PurgeProducts_sync", + "regionTag": "retail_v2beta_generated_ProductService_RemoveLocalInventories_sync", "segments": [ { "end": 56, @@ -5942,7 +7246,7 @@ "type": "RESPONSE_HANDLING" } ], - "title": "retail_v2beta_generated_product_service_purge_products_sync.py" + "title": "retail_v2beta_generated_product_service_remove_local_inventories_sync.py" }, { "canonical": true, @@ -5952,23 +7256,27 @@ "fullName": "google.cloud.retail_v2beta.ProductServiceAsyncClient", "shortName": "ProductServiceAsyncClient" }, - "fullName": "google.cloud.retail_v2beta.ProductServiceAsyncClient.remove_fulfillment_places", + "fullName": "google.cloud.retail_v2beta.ProductServiceAsyncClient.set_inventory", "method": { - "fullName": "google.cloud.retail.v2beta.ProductService.RemoveFulfillmentPlaces", + "fullName": "google.cloud.retail.v2beta.ProductService.SetInventory", "service": { "fullName": "google.cloud.retail.v2beta.ProductService", "shortName": "ProductService" }, - "shortName": "RemoveFulfillmentPlaces" + "shortName": "SetInventory" }, "parameters": [ { "name": "request", - "type": "google.cloud.retail_v2beta.types.RemoveFulfillmentPlacesRequest" + "type": "google.cloud.retail_v2beta.types.SetInventoryRequest" }, { - "name": "product", - "type": "str" + "name": "inventory", + "type": "google.cloud.retail_v2beta.types.Product" + }, + { + "name": "set_mask", + "type": "google.protobuf.field_mask_pb2.FieldMask" }, { "name": "retry", @@ -5984,21 +7292,21 @@ } ], "resultType": "google.api_core.operation_async.AsyncOperation", - "shortName": "remove_fulfillment_places" + "shortName": "set_inventory" }, - "description": "Sample for RemoveFulfillmentPlaces", - "file": "retail_v2beta_generated_product_service_remove_fulfillment_places_async.py", + "description": "Sample for SetInventory", + "file": "retail_v2beta_generated_product_service_set_inventory_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "retail_v2beta_generated_ProductService_RemoveFulfillmentPlaces_async", + "regionTag": "retail_v2beta_generated_ProductService_SetInventory_async", "segments": [ { - "end": 57, + "end": 58, "start": 27, "type": "FULL" }, { - "end": 57, + "end": 58, "start": 27, "type": "SHORT" }, @@ -6008,22 +7316,22 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 47, + "end": 48, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 54, - "start": 48, + "end": 55, + "start": 49, "type": "REQUEST_EXECUTION" }, { - "end": 58, - "start": 55, + "end": 59, + "start": 56, "type": "RESPONSE_HANDLING" } ], - "title": "retail_v2beta_generated_product_service_remove_fulfillment_places_async.py" + "title": "retail_v2beta_generated_product_service_set_inventory_async.py" }, { "canonical": true, @@ -6032,23 +7340,27 @@ "fullName": "google.cloud.retail_v2beta.ProductServiceClient", "shortName": "ProductServiceClient" }, - "fullName": "google.cloud.retail_v2beta.ProductServiceClient.remove_fulfillment_places", + "fullName": "google.cloud.retail_v2beta.ProductServiceClient.set_inventory", "method": { - "fullName": "google.cloud.retail.v2beta.ProductService.RemoveFulfillmentPlaces", + "fullName": "google.cloud.retail.v2beta.ProductService.SetInventory", "service": { "fullName": "google.cloud.retail.v2beta.ProductService", "shortName": "ProductService" }, - "shortName": "RemoveFulfillmentPlaces" + "shortName": "SetInventory" }, "parameters": [ { "name": "request", - "type": "google.cloud.retail_v2beta.types.RemoveFulfillmentPlacesRequest" + "type": "google.cloud.retail_v2beta.types.SetInventoryRequest" }, { - "name": "product", - "type": "str" + "name": "inventory", + "type": "google.cloud.retail_v2beta.types.Product" + }, + { + "name": "set_mask", + "type": "google.protobuf.field_mask_pb2.FieldMask" }, { "name": "retry", @@ -6064,21 +7376,21 @@ } ], "resultType": "google.api_core.operation.Operation", - "shortName": "remove_fulfillment_places" + "shortName": "set_inventory" }, - "description": "Sample for RemoveFulfillmentPlaces", - "file": "retail_v2beta_generated_product_service_remove_fulfillment_places_sync.py", + "description": "Sample for SetInventory", + "file": "retail_v2beta_generated_product_service_set_inventory_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "retail_v2beta_generated_ProductService_RemoveFulfillmentPlaces_sync", + "regionTag": "retail_v2beta_generated_ProductService_SetInventory_sync", "segments": [ { - "end": 57, + "end": 58, "start": 27, "type": "FULL" }, { - "end": 57, + "end": 58, "start": 27, "type": "SHORT" }, @@ -6088,22 +7400,22 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 47, + "end": 48, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 54, - "start": 48, + "end": 55, + "start": 49, "type": "REQUEST_EXECUTION" }, { - "end": 58, - "start": 55, + "end": 59, + "start": 56, "type": "RESPONSE_HANDLING" } ], - "title": "retail_v2beta_generated_product_service_remove_fulfillment_places_sync.py" + "title": "retail_v2beta_generated_product_service_set_inventory_sync.py" }, { "canonical": true, @@ -6113,23 +7425,27 @@ "fullName": "google.cloud.retail_v2beta.ProductServiceAsyncClient", "shortName": "ProductServiceAsyncClient" }, - "fullName": "google.cloud.retail_v2beta.ProductServiceAsyncClient.remove_local_inventories", + "fullName": "google.cloud.retail_v2beta.ProductServiceAsyncClient.update_product", "method": { - "fullName": "google.cloud.retail.v2beta.ProductService.RemoveLocalInventories", + "fullName": "google.cloud.retail.v2beta.ProductService.UpdateProduct", "service": { "fullName": "google.cloud.retail.v2beta.ProductService", "shortName": "ProductService" }, - "shortName": "RemoveLocalInventories" + "shortName": "UpdateProduct" }, "parameters": [ { "name": "request", - "type": "google.cloud.retail_v2beta.types.RemoveLocalInventoriesRequest" + "type": "google.cloud.retail_v2beta.types.UpdateProductRequest" }, { "name": "product", - "type": "str" + "type": "google.cloud.retail_v2beta.types.Product" + }, + { + "name": "update_mask", + "type": "google.protobuf.field_mask_pb2.FieldMask" }, { "name": "retry", @@ -6144,22 +7460,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.api_core.operation_async.AsyncOperation", - "shortName": "remove_local_inventories" + "resultType": "google.cloud.retail_v2beta.types.Product", + "shortName": "update_product" }, - "description": "Sample for RemoveLocalInventories", - "file": "retail_v2beta_generated_product_service_remove_local_inventories_async.py", + "description": "Sample for UpdateProduct", + "file": "retail_v2beta_generated_product_service_update_product_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "retail_v2beta_generated_ProductService_RemoveLocalInventories_async", + "regionTag": "retail_v2beta_generated_ProductService_UpdateProduct_async", "segments": [ { - "end": 56, + "end": 54, "start": 27, "type": "FULL" }, { - "end": 56, + "end": 54, "start": 27, "type": "SHORT" }, @@ -6169,22 +7485,22 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 46, + "end": 48, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 53, - "start": 47, + "end": 51, + "start": 49, "type": "REQUEST_EXECUTION" }, { - "end": 57, - "start": 54, + "end": 55, + "start": 52, "type": "RESPONSE_HANDLING" } ], - "title": "retail_v2beta_generated_product_service_remove_local_inventories_async.py" + "title": "retail_v2beta_generated_product_service_update_product_async.py" }, { "canonical": true, @@ -6193,23 +7509,27 @@ "fullName": "google.cloud.retail_v2beta.ProductServiceClient", "shortName": "ProductServiceClient" }, - "fullName": "google.cloud.retail_v2beta.ProductServiceClient.remove_local_inventories", + "fullName": "google.cloud.retail_v2beta.ProductServiceClient.update_product", "method": { - "fullName": "google.cloud.retail.v2beta.ProductService.RemoveLocalInventories", + "fullName": "google.cloud.retail.v2beta.ProductService.UpdateProduct", "service": { "fullName": "google.cloud.retail.v2beta.ProductService", "shortName": "ProductService" }, - "shortName": "RemoveLocalInventories" + "shortName": "UpdateProduct" }, "parameters": [ { "name": "request", - "type": "google.cloud.retail_v2beta.types.RemoveLocalInventoriesRequest" + "type": "google.cloud.retail_v2beta.types.UpdateProductRequest" }, { "name": "product", - "type": "str" + "type": "google.cloud.retail_v2beta.types.Product" + }, + { + "name": "update_mask", + "type": "google.protobuf.field_mask_pb2.FieldMask" }, { "name": "retry", @@ -6224,22 +7544,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.api_core.operation.Operation", - "shortName": "remove_local_inventories" + "resultType": "google.cloud.retail_v2beta.types.Product", + "shortName": "update_product" }, - "description": "Sample for RemoveLocalInventories", - "file": "retail_v2beta_generated_product_service_remove_local_inventories_sync.py", + "description": "Sample for UpdateProduct", + "file": "retail_v2beta_generated_product_service_update_product_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "retail_v2beta_generated_ProductService_RemoveLocalInventories_sync", + "regionTag": "retail_v2beta_generated_ProductService_UpdateProduct_sync", "segments": [ { - "end": 56, + "end": 54, "start": 27, "type": "FULL" }, { - "end": 56, + "end": 54, "start": 27, "type": "SHORT" }, @@ -6249,52 +7569,48 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 46, + "end": 48, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 53, - "start": 47, + "end": 51, + "start": 49, "type": "REQUEST_EXECUTION" }, { - "end": 57, - "start": 54, + "end": 55, + "start": 52, "type": "RESPONSE_HANDLING" } ], - "title": "retail_v2beta_generated_product_service_remove_local_inventories_sync.py" + "title": "retail_v2beta_generated_product_service_update_product_sync.py" }, { "canonical": true, "clientMethod": { "async": true, "client": { - "fullName": "google.cloud.retail_v2beta.ProductServiceAsyncClient", - "shortName": "ProductServiceAsyncClient" + "fullName": "google.cloud.retail_v2beta.ProjectServiceAsyncClient", + "shortName": "ProjectServiceAsyncClient" }, - "fullName": "google.cloud.retail_v2beta.ProductServiceAsyncClient.set_inventory", + "fullName": "google.cloud.retail_v2beta.ProjectServiceAsyncClient.get_alert_config", "method": { - "fullName": "google.cloud.retail.v2beta.ProductService.SetInventory", + "fullName": "google.cloud.retail.v2beta.ProjectService.GetAlertConfig", "service": { - "fullName": "google.cloud.retail.v2beta.ProductService", - "shortName": "ProductService" + "fullName": "google.cloud.retail.v2beta.ProjectService", + "shortName": "ProjectService" }, - "shortName": "SetInventory" + "shortName": "GetAlertConfig" }, "parameters": [ { "name": "request", - "type": "google.cloud.retail_v2beta.types.SetInventoryRequest" - }, - { - "name": "inventory", - "type": "google.cloud.retail_v2beta.types.Product" + "type": "google.cloud.retail_v2beta.types.GetAlertConfigRequest" }, { - "name": "set_mask", - "type": "google.protobuf.field_mask_pb2.FieldMask" + "name": "name", + "type": "str" }, { "name": "retry", @@ -6309,22 +7625,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.api_core.operation_async.AsyncOperation", - "shortName": "set_inventory" + "resultType": "google.cloud.retail_v2beta.types.AlertConfig", + "shortName": "get_alert_config" }, - "description": "Sample for SetInventory", - "file": "retail_v2beta_generated_product_service_set_inventory_async.py", + "description": "Sample for GetAlertConfig", + "file": "retail_v2beta_generated_project_service_get_alert_config_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "retail_v2beta_generated_ProductService_SetInventory_async", + "regionTag": "retail_v2beta_generated_ProjectService_GetAlertConfig_async", "segments": [ { - "end": 58, + "end": 51, "start": 27, "type": "FULL" }, { - "end": 58, + "end": 51, "start": 27, "type": "SHORT" }, @@ -6334,51 +7650,47 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 48, + "end": 45, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 55, - "start": 49, + "end": 48, + "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 59, - "start": 56, + "end": 52, + "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "retail_v2beta_generated_product_service_set_inventory_async.py" + "title": "retail_v2beta_generated_project_service_get_alert_config_async.py" }, { "canonical": true, "clientMethod": { "client": { - "fullName": "google.cloud.retail_v2beta.ProductServiceClient", - "shortName": "ProductServiceClient" + "fullName": "google.cloud.retail_v2beta.ProjectServiceClient", + "shortName": "ProjectServiceClient" }, - "fullName": "google.cloud.retail_v2beta.ProductServiceClient.set_inventory", + "fullName": "google.cloud.retail_v2beta.ProjectServiceClient.get_alert_config", "method": { - "fullName": "google.cloud.retail.v2beta.ProductService.SetInventory", + "fullName": "google.cloud.retail.v2beta.ProjectService.GetAlertConfig", "service": { - "fullName": "google.cloud.retail.v2beta.ProductService", - "shortName": "ProductService" + "fullName": "google.cloud.retail.v2beta.ProjectService", + "shortName": "ProjectService" }, - "shortName": "SetInventory" + "shortName": "GetAlertConfig" }, "parameters": [ { "name": "request", - "type": "google.cloud.retail_v2beta.types.SetInventoryRequest" - }, - { - "name": "inventory", - "type": "google.cloud.retail_v2beta.types.Product" + "type": "google.cloud.retail_v2beta.types.GetAlertConfigRequest" }, { - "name": "set_mask", - "type": "google.protobuf.field_mask_pb2.FieldMask" + "name": "name", + "type": "str" }, { "name": "retry", @@ -6393,22 +7705,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.api_core.operation.Operation", - "shortName": "set_inventory" + "resultType": "google.cloud.retail_v2beta.types.AlertConfig", + "shortName": "get_alert_config" }, - "description": "Sample for SetInventory", - "file": "retail_v2beta_generated_product_service_set_inventory_sync.py", + "description": "Sample for GetAlertConfig", + "file": "retail_v2beta_generated_project_service_get_alert_config_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "retail_v2beta_generated_ProductService_SetInventory_sync", + "regionTag": "retail_v2beta_generated_ProjectService_GetAlertConfig_sync", "segments": [ { - "end": 58, + "end": 51, "start": 27, "type": "FULL" }, { - "end": 58, + "end": 51, "start": 27, "type": "SHORT" }, @@ -6418,48 +7730,48 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 48, + "end": 45, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 55, - "start": 49, + "end": 48, + "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 59, - "start": 56, + "end": 52, + "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "retail_v2beta_generated_product_service_set_inventory_sync.py" + "title": "retail_v2beta_generated_project_service_get_alert_config_sync.py" }, { "canonical": true, "clientMethod": { "async": true, "client": { - "fullName": "google.cloud.retail_v2beta.ProductServiceAsyncClient", - "shortName": "ProductServiceAsyncClient" + "fullName": "google.cloud.retail_v2beta.ProjectServiceAsyncClient", + "shortName": "ProjectServiceAsyncClient" }, - "fullName": "google.cloud.retail_v2beta.ProductServiceAsyncClient.update_product", + "fullName": "google.cloud.retail_v2beta.ProjectServiceAsyncClient.update_alert_config", "method": { - "fullName": "google.cloud.retail.v2beta.ProductService.UpdateProduct", + "fullName": "google.cloud.retail.v2beta.ProjectService.UpdateAlertConfig", "service": { - "fullName": "google.cloud.retail.v2beta.ProductService", - "shortName": "ProductService" + "fullName": "google.cloud.retail.v2beta.ProjectService", + "shortName": "ProjectService" }, - "shortName": "UpdateProduct" + "shortName": "UpdateAlertConfig" }, "parameters": [ { "name": "request", - "type": "google.cloud.retail_v2beta.types.UpdateProductRequest" + "type": "google.cloud.retail_v2beta.types.UpdateAlertConfigRequest" }, { - "name": "product", - "type": "google.cloud.retail_v2beta.types.Product" + "name": "alert_config", + "type": "google.cloud.retail_v2beta.types.AlertConfig" }, { "name": "update_mask", @@ -6478,14 +7790,14 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.retail_v2beta.types.Product", - "shortName": "update_product" + "resultType": "google.cloud.retail_v2beta.types.AlertConfig", + "shortName": "update_alert_config" }, - "description": "Sample for UpdateProduct", - "file": "retail_v2beta_generated_product_service_update_product_async.py", + "description": "Sample for UpdateAlertConfig", + "file": "retail_v2beta_generated_project_service_update_alert_config_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "retail_v2beta_generated_ProductService_UpdateProduct_async", + "regionTag": "retail_v2beta_generated_ProjectService_UpdateAlertConfig_async", "segments": [ { "end": 54, @@ -6518,32 +7830,32 @@ "type": "RESPONSE_HANDLING" } ], - "title": "retail_v2beta_generated_product_service_update_product_async.py" + "title": "retail_v2beta_generated_project_service_update_alert_config_async.py" }, { "canonical": true, "clientMethod": { "client": { - "fullName": "google.cloud.retail_v2beta.ProductServiceClient", - "shortName": "ProductServiceClient" + "fullName": "google.cloud.retail_v2beta.ProjectServiceClient", + "shortName": "ProjectServiceClient" }, - "fullName": "google.cloud.retail_v2beta.ProductServiceClient.update_product", + "fullName": "google.cloud.retail_v2beta.ProjectServiceClient.update_alert_config", "method": { - "fullName": "google.cloud.retail.v2beta.ProductService.UpdateProduct", + "fullName": "google.cloud.retail.v2beta.ProjectService.UpdateAlertConfig", "service": { - "fullName": "google.cloud.retail.v2beta.ProductService", - "shortName": "ProductService" + "fullName": "google.cloud.retail.v2beta.ProjectService", + "shortName": "ProjectService" }, - "shortName": "UpdateProduct" + "shortName": "UpdateAlertConfig" }, "parameters": [ { "name": "request", - "type": "google.cloud.retail_v2beta.types.UpdateProductRequest" + "type": "google.cloud.retail_v2beta.types.UpdateAlertConfigRequest" }, { - "name": "product", - "type": "google.cloud.retail_v2beta.types.Product" + "name": "alert_config", + "type": "google.cloud.retail_v2beta.types.AlertConfig" }, { "name": "update_mask", @@ -6562,14 +7874,14 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.retail_v2beta.types.Product", - "shortName": "update_product" + "resultType": "google.cloud.retail_v2beta.types.AlertConfig", + "shortName": "update_alert_config" }, - "description": "Sample for UpdateProduct", - "file": "retail_v2beta_generated_product_service_update_product_sync.py", + "description": "Sample for UpdateAlertConfig", + "file": "retail_v2beta_generated_project_service_update_alert_config_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "retail_v2beta_generated_ProductService_UpdateProduct_sync", + "regionTag": "retail_v2beta_generated_ProjectService_UpdateAlertConfig_sync", "segments": [ { "end": 54, @@ -6602,7 +7914,7 @@ "type": "RESPONSE_HANDLING" } ], - "title": "retail_v2beta_generated_product_service_update_product_sync.py" + "title": "retail_v2beta_generated_project_service_update_alert_config_sync.py" }, { "canonical": true, @@ -8055,6 +9367,159 @@ ], "title": "retail_v2beta_generated_user_event_service_collect_user_event_sync.py" }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.retail_v2beta.UserEventServiceAsyncClient", + "shortName": "UserEventServiceAsyncClient" + }, + "fullName": "google.cloud.retail_v2beta.UserEventServiceAsyncClient.export_user_events", + "method": { + "fullName": "google.cloud.retail.v2beta.UserEventService.ExportUserEvents", + "service": { + "fullName": "google.cloud.retail.v2beta.UserEventService", + "shortName": "UserEventService" + }, + "shortName": "ExportUserEvents" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.retail_v2beta.types.ExportUserEventsRequest" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.api_core.operation_async.AsyncOperation", + "shortName": "export_user_events" + }, + "description": "Sample for ExportUserEvents", + "file": "retail_v2beta_generated_user_event_service_export_user_events_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "retail_v2beta_generated_UserEventService_ExportUserEvents_async", + "segments": [ + { + "end": 59, + "start": 27, + "type": "FULL" + }, + { + "end": 59, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 49, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 56, + "start": 50, + "type": "REQUEST_EXECUTION" + }, + { + "end": 60, + "start": 57, + "type": "RESPONSE_HANDLING" + } + ], + "title": "retail_v2beta_generated_user_event_service_export_user_events_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.retail_v2beta.UserEventServiceClient", + "shortName": "UserEventServiceClient" + }, + "fullName": "google.cloud.retail_v2beta.UserEventServiceClient.export_user_events", + "method": { + "fullName": "google.cloud.retail.v2beta.UserEventService.ExportUserEvents", + "service": { + "fullName": "google.cloud.retail.v2beta.UserEventService", + "shortName": "UserEventService" + }, + "shortName": "ExportUserEvents" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.retail_v2beta.types.ExportUserEventsRequest" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.api_core.operation.Operation", + "shortName": "export_user_events" + }, + "description": "Sample for ExportUserEvents", + "file": "retail_v2beta_generated_user_event_service_export_user_events_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "retail_v2beta_generated_UserEventService_ExportUserEvents_sync", + "segments": [ + { + "end": 59, + "start": 27, + "type": "FULL" + }, + { + "end": 59, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 49, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 56, + "start": 50, + "type": "REQUEST_EXECUTION" + }, + { + "end": 60, + "start": 57, + "type": "RESPONSE_HANDLING" + } + ], + "title": "retail_v2beta_generated_user_event_service_export_user_events_sync.py" + }, { "canonical": true, "clientMethod": { diff --git a/packages/google-cloud-retail/scripts/fixup_retail_v2_keywords.py b/packages/google-cloud-retail/scripts/fixup_retail_v2_keywords.py index 53664c5299f2..837ef6b34637 100644 --- a/packages/google-cloud-retail/scripts/fixup_retail_v2_keywords.py +++ b/packages/google-cloud-retail/scripts/fixup_retail_v2_keywords.py @@ -43,6 +43,7 @@ class retailCallTransformer(cst.CSTTransformer): 'add_control': ('serving_config', 'control_id', ), 'add_fulfillment_places': ('product', 'type_', 'place_ids', 'add_time', 'allow_missing', ), 'add_local_inventories': ('product', 'local_inventories', 'add_mask', 'add_time', 'allow_missing', ), + 'batch_update_generative_question_configs': ('requests', 'parent', ), 'collect_user_event': ('parent', 'user_event', 'prebuilt_rule', 'uri', 'ets', 'raw_json', ), 'complete_query': ('catalog', 'query', 'visitor_id', 'language_codes', 'device_type', 'dataset', 'max_suggestions', 'enable_attribute_suggestions', 'entity', ), 'create_control': ('parent', 'control', 'control_id', ), @@ -58,6 +59,7 @@ class retailCallTransformer(cst.CSTTransformer): 'get_completion_config': ('name', ), 'get_control': ('name', ), 'get_default_branch': ('catalog', ), + 'get_generative_questions_feature_config': ('catalog', ), 'get_model': ('name', ), 'get_product': ('name', ), 'get_serving_config': ('name', ), @@ -66,6 +68,7 @@ class retailCallTransformer(cst.CSTTransformer): 'import_user_events': ('parent', 'input_config', 'errors_config', ), 'list_catalogs': ('parent', 'page_size', 'page_token', ), 'list_controls': ('parent', 'page_size', 'page_token', 'filter', ), + 'list_generative_question_configs': ('parent', ), 'list_models': ('parent', 'page_size', 'page_token', ), 'list_products': ('parent', 'page_size', 'page_token', 'filter', 'read_mask', ), 'list_serving_configs': ('parent', 'page_size', 'page_token', ), @@ -80,7 +83,7 @@ class retailCallTransformer(cst.CSTTransformer): 'remove_local_inventories': ('product', 'place_ids', 'remove_time', 'allow_missing', ), 'replace_catalog_attribute': ('attributes_config', 'catalog_attribute', 'update_mask', ), 'resume_model': ('name', ), - 'search': ('placement', 'visitor_id', 'branch', 'query', 'user_info', 'page_size', 'page_token', 'offset', 'filter', 'canonical_filter', 'order_by', 'facet_specs', 'dynamic_facet_spec', 'boost_spec', 'query_expansion_spec', 'variant_rollup_keys', 'page_categories', 'search_mode', 'personalization_spec', 'labels', 'spell_correction_spec', 'entity', ), + 'search': ('placement', 'visitor_id', 'branch', 'query', 'user_info', 'page_size', 'page_token', 'offset', 'filter', 'canonical_filter', 'order_by', 'facet_specs', 'dynamic_facet_spec', 'boost_spec', 'query_expansion_spec', 'variant_rollup_keys', 'page_categories', 'search_mode', 'personalization_spec', 'labels', 'spell_correction_spec', 'entity', 'conversational_search_spec', 'tile_navigation_spec', ), 'set_default_branch': ('catalog', 'branch_id', 'note', 'force', ), 'set_inventory': ('inventory', 'set_mask', 'set_time', 'allow_missing', ), 'tune_model': ('name', ), @@ -88,6 +91,8 @@ class retailCallTransformer(cst.CSTTransformer): 'update_catalog': ('catalog', 'update_mask', ), 'update_completion_config': ('completion_config', 'update_mask', ), 'update_control': ('control', 'update_mask', ), + 'update_generative_question_config': ('generative_question_config', 'update_mask', ), + 'update_generative_questions_feature_config': ('generative_questions_feature_config', 'update_mask', ), 'update_model': ('model', 'update_mask', ), 'update_product': ('product', 'update_mask', 'allow_missing', ), 'update_serving_config': ('serving_config', 'update_mask', ), diff --git a/packages/google-cloud-retail/scripts/fixup_retail_v2alpha_keywords.py b/packages/google-cloud-retail/scripts/fixup_retail_v2alpha_keywords.py index a68b750b304a..e84a9fb47929 100644 --- a/packages/google-cloud-retail/scripts/fixup_retail_v2alpha_keywords.py +++ b/packages/google-cloud-retail/scripts/fixup_retail_v2alpha_keywords.py @@ -45,6 +45,7 @@ class retailCallTransformer(cst.CSTTransformer): 'add_fulfillment_places': ('product', 'type_', 'place_ids', 'add_time', 'allow_missing', ), 'add_local_inventories': ('product', 'local_inventories', 'add_mask', 'add_time', 'allow_missing', ), 'batch_remove_catalog_attributes': ('attributes_config', 'attribute_keys', ), + 'batch_update_generative_question_configs': ('requests', 'parent', ), 'collect_user_event': ('parent', 'user_event', 'prebuilt_rule', 'uri', 'ets', 'raw_json', ), 'complete_query': ('catalog', 'query', 'visitor_id', 'language_codes', 'device_type', 'dataset', 'max_suggestions', 'enable_attribute_suggestions', 'entity', ), 'create_control': ('parent', 'control', 'control_id', ), @@ -59,12 +60,15 @@ class retailCallTransformer(cst.CSTTransformer): 'delete_serving_config': ('name', ), 'enroll_solution': ('project', 'solution', ), 'export_analytics_metrics': ('catalog', 'output_config', 'filter', ), + 'export_products': ('parent', 'output_config', 'filter', ), + 'export_user_events': ('parent', 'output_config', 'filter', ), 'get_alert_config': ('name', ), 'get_attributes_config': ('name', ), 'get_branch': ('name', 'view', ), 'get_completion_config': ('name', ), 'get_control': ('name', ), 'get_default_branch': ('catalog', ), + 'get_generative_questions_feature_config': ('catalog', ), 'get_logging_config': ('name', ), 'get_model': ('name', ), 'get_product': ('name', ), @@ -77,6 +81,7 @@ class retailCallTransformer(cst.CSTTransformer): 'list_catalogs': ('parent', 'page_size', 'page_token', ), 'list_controls': ('parent', 'page_size', 'page_token', 'filter', ), 'list_enrolled_solutions': ('parent', ), + 'list_generative_question_configs': ('parent', ), 'list_merchant_center_account_links': ('parent', ), 'list_models': ('parent', 'page_size', 'page_token', ), 'list_products': ('parent', 'page_size', 'page_token', 'filter', 'read_mask', 'require_total_size', ), @@ -92,7 +97,7 @@ class retailCallTransformer(cst.CSTTransformer): 'remove_local_inventories': ('product', 'place_ids', 'remove_time', 'allow_missing', ), 'replace_catalog_attribute': ('attributes_config', 'catalog_attribute', 'update_mask', ), 'resume_model': ('name', ), - 'search': ('placement', 'visitor_id', 'branch', 'query', 'user_info', 'page_size', 'page_token', 'offset', 'filter', 'canonical_filter', 'order_by', 'facet_specs', 'dynamic_facet_spec', 'boost_spec', 'query_expansion_spec', 'relevance_threshold', 'variant_rollup_keys', 'page_categories', 'search_mode', 'personalization_spec', 'labels', 'spell_correction_spec', 'entity', ), + 'search': ('placement', 'visitor_id', 'branch', 'query', 'user_info', 'page_size', 'page_token', 'offset', 'filter', 'canonical_filter', 'order_by', 'facet_specs', 'dynamic_facet_spec', 'boost_spec', 'query_expansion_spec', 'relevance_threshold', 'variant_rollup_keys', 'page_categories', 'search_mode', 'personalization_spec', 'labels', 'spell_correction_spec', 'entity', 'conversational_search_spec', 'tile_navigation_spec', ), 'set_default_branch': ('catalog', 'branch_id', 'note', 'force', ), 'set_inventory': ('inventory', 'set_mask', 'set_time', 'allow_missing', ), 'tune_model': ('name', ), @@ -101,6 +106,8 @@ class retailCallTransformer(cst.CSTTransformer): 'update_catalog': ('catalog', 'update_mask', ), 'update_completion_config': ('completion_config', 'update_mask', ), 'update_control': ('control', 'update_mask', ), + 'update_generative_question_config': ('generative_question_config', 'update_mask', ), + 'update_generative_questions_feature_config': ('generative_questions_feature_config', 'update_mask', ), 'update_logging_config': ('logging_config', 'update_mask', ), 'update_model': ('model', 'update_mask', ), 'update_product': ('product', 'update_mask', 'allow_missing', ), diff --git a/packages/google-cloud-retail/scripts/fixup_retail_v2beta_keywords.py b/packages/google-cloud-retail/scripts/fixup_retail_v2beta_keywords.py index 03bc7e8515b3..f639c9354280 100644 --- a/packages/google-cloud-retail/scripts/fixup_retail_v2beta_keywords.py +++ b/packages/google-cloud-retail/scripts/fixup_retail_v2beta_keywords.py @@ -44,6 +44,7 @@ class retailCallTransformer(cst.CSTTransformer): 'add_fulfillment_places': ('product', 'type_', 'place_ids', 'add_time', 'allow_missing', ), 'add_local_inventories': ('product', 'local_inventories', 'add_mask', 'add_time', 'allow_missing', ), 'batch_remove_catalog_attributes': ('attributes_config', 'attribute_keys', ), + 'batch_update_generative_question_configs': ('requests', 'parent', ), 'collect_user_event': ('parent', 'user_event', 'prebuilt_rule', 'uri', 'ets', 'raw_json', ), 'complete_query': ('catalog', 'query', 'visitor_id', 'language_codes', 'device_type', 'dataset', 'max_suggestions', 'enable_attribute_suggestions', 'entity', ), 'create_control': ('parent', 'control', 'control_id', ), @@ -55,10 +56,14 @@ class retailCallTransformer(cst.CSTTransformer): 'delete_product': ('name', ), 'delete_serving_config': ('name', ), 'export_analytics_metrics': ('catalog', 'output_config', 'filter', ), + 'export_products': ('parent', 'output_config', 'filter', ), + 'export_user_events': ('parent', 'output_config', 'filter', ), + 'get_alert_config': ('name', ), 'get_attributes_config': ('name', ), 'get_completion_config': ('name', ), 'get_control': ('name', ), 'get_default_branch': ('catalog', ), + 'get_generative_questions_feature_config': ('catalog', ), 'get_model': ('name', ), 'get_product': ('name', ), 'get_serving_config': ('name', ), @@ -67,6 +72,7 @@ class retailCallTransformer(cst.CSTTransformer): 'import_user_events': ('parent', 'input_config', 'errors_config', ), 'list_catalogs': ('parent', 'page_size', 'page_token', ), 'list_controls': ('parent', 'page_size', 'page_token', 'filter', ), + 'list_generative_question_configs': ('parent', ), 'list_models': ('parent', 'page_size', 'page_token', ), 'list_products': ('parent', 'page_size', 'page_token', 'filter', 'read_mask', ), 'list_serving_configs': ('parent', 'page_size', 'page_token', ), @@ -81,14 +87,17 @@ class retailCallTransformer(cst.CSTTransformer): 'remove_local_inventories': ('product', 'place_ids', 'remove_time', 'allow_missing', ), 'replace_catalog_attribute': ('attributes_config', 'catalog_attribute', 'update_mask', ), 'resume_model': ('name', ), - 'search': ('placement', 'visitor_id', 'branch', 'query', 'user_info', 'page_size', 'page_token', 'offset', 'filter', 'canonical_filter', 'order_by', 'facet_specs', 'dynamic_facet_spec', 'boost_spec', 'query_expansion_spec', 'variant_rollup_keys', 'page_categories', 'search_mode', 'personalization_spec', 'labels', 'spell_correction_spec', 'entity', ), + 'search': ('placement', 'visitor_id', 'branch', 'query', 'user_info', 'page_size', 'page_token', 'offset', 'filter', 'canonical_filter', 'order_by', 'facet_specs', 'dynamic_facet_spec', 'boost_spec', 'query_expansion_spec', 'variant_rollup_keys', 'page_categories', 'search_mode', 'personalization_spec', 'labels', 'spell_correction_spec', 'entity', 'conversational_search_spec', 'tile_navigation_spec', ), 'set_default_branch': ('catalog', 'branch_id', 'note', 'force', ), 'set_inventory': ('inventory', 'set_mask', 'set_time', 'allow_missing', ), 'tune_model': ('name', ), + 'update_alert_config': ('alert_config', 'update_mask', ), 'update_attributes_config': ('attributes_config', 'update_mask', ), 'update_catalog': ('catalog', 'update_mask', ), 'update_completion_config': ('completion_config', 'update_mask', ), 'update_control': ('control', 'update_mask', ), + 'update_generative_question_config': ('generative_question_config', 'update_mask', ), + 'update_generative_questions_feature_config': ('generative_questions_feature_config', 'update_mask', ), 'update_model': ('model', 'update_mask', ), 'update_product': ('product', 'update_mask', 'allow_missing', ), 'update_serving_config': ('serving_config', 'update_mask', ), diff --git a/packages/google-cloud-retail/tests/unit/gapic/retail_v2/test_generative_question_service.py b/packages/google-cloud-retail/tests/unit/gapic/retail_v2/test_generative_question_service.py new file mode 100644 index 000000000000..a21da9ae519f --- /dev/null +++ b/packages/google-cloud-retail/tests/unit/gapic/retail_v2/test_generative_question_service.py @@ -0,0 +1,6444 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import os + +# try/except added for compatibility with python < 3.8 +try: + from unittest import mock + from unittest.mock import AsyncMock # pragma: NO COVER +except ImportError: # pragma: NO COVER + import mock + +from collections.abc import Iterable +import json +import math + +from google.api_core import gapic_v1, grpc_helpers, grpc_helpers_async, path_template +from google.api_core import api_core_version, client_options +from google.api_core import exceptions as core_exceptions +from google.api_core import retry as retries +import google.auth +from google.auth import credentials as ga_credentials +from google.auth.exceptions import MutualTLSChannelError +from google.cloud.location import locations_pb2 +from google.longrunning import operations_pb2 # type: ignore +from google.oauth2 import service_account +from google.protobuf import field_mask_pb2 # type: ignore +from google.protobuf import json_format +import grpc +from grpc.experimental import aio +from proto.marshal.rules import wrappers +from proto.marshal.rules.dates import DurationRule, TimestampRule +import pytest +from requests import PreparedRequest, Request, Response +from requests.sessions import Session + +from google.cloud.retail_v2.services.generative_question_service import ( + GenerativeQuestionServiceAsyncClient, + GenerativeQuestionServiceClient, + transports, +) +from google.cloud.retail_v2.types import ( + generative_question, + generative_question_service, +) + + +def client_cert_source_callback(): + return b"cert bytes", b"key bytes" + + +# If default endpoint is localhost, then default mtls endpoint will be the same. +# This method modifies the default endpoint so the client can produce a different +# mtls endpoint for endpoint testing purposes. +def modify_default_endpoint(client): + return ( + "foo.googleapis.com" + if ("localhost" in client.DEFAULT_ENDPOINT) + else client.DEFAULT_ENDPOINT + ) + + +# If default endpoint template is localhost, then default mtls endpoint will be the same. +# This method modifies the default endpoint template so the client can produce a different +# mtls endpoint for endpoint testing purposes. +def modify_default_endpoint_template(client): + return ( + "test.{UNIVERSE_DOMAIN}" + if ("localhost" in client._DEFAULT_ENDPOINT_TEMPLATE) + else client._DEFAULT_ENDPOINT_TEMPLATE + ) + + +def test__get_default_mtls_endpoint(): + api_endpoint = "example.googleapis.com" + api_mtls_endpoint = "example.mtls.googleapis.com" + sandbox_endpoint = "example.sandbox.googleapis.com" + sandbox_mtls_endpoint = "example.mtls.sandbox.googleapis.com" + non_googleapi = "api.example.com" + + assert GenerativeQuestionServiceClient._get_default_mtls_endpoint(None) is None + assert ( + GenerativeQuestionServiceClient._get_default_mtls_endpoint(api_endpoint) + == api_mtls_endpoint + ) + assert ( + GenerativeQuestionServiceClient._get_default_mtls_endpoint(api_mtls_endpoint) + == api_mtls_endpoint + ) + assert ( + GenerativeQuestionServiceClient._get_default_mtls_endpoint(sandbox_endpoint) + == sandbox_mtls_endpoint + ) + assert ( + GenerativeQuestionServiceClient._get_default_mtls_endpoint( + sandbox_mtls_endpoint + ) + == sandbox_mtls_endpoint + ) + assert ( + GenerativeQuestionServiceClient._get_default_mtls_endpoint(non_googleapi) + == non_googleapi + ) + + +def test__read_environment_variables(): + assert GenerativeQuestionServiceClient._read_environment_variables() == ( + False, + "auto", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "true"}): + assert GenerativeQuestionServiceClient._read_environment_variables() == ( + True, + "auto", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "false"}): + assert GenerativeQuestionServiceClient._read_environment_variables() == ( + False, + "auto", + None, + ) + + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"} + ): + with pytest.raises(ValueError) as excinfo: + GenerativeQuestionServiceClient._read_environment_variables() + assert ( + str(excinfo.value) + == "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): + assert GenerativeQuestionServiceClient._read_environment_variables() == ( + False, + "never", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): + assert GenerativeQuestionServiceClient._read_environment_variables() == ( + False, + "always", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "auto"}): + assert GenerativeQuestionServiceClient._read_environment_variables() == ( + False, + "auto", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "Unsupported"}): + with pytest.raises(MutualTLSChannelError) as excinfo: + GenerativeQuestionServiceClient._read_environment_variables() + assert ( + str(excinfo.value) + == "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`" + ) + + with mock.patch.dict(os.environ, {"GOOGLE_CLOUD_UNIVERSE_DOMAIN": "foo.com"}): + assert GenerativeQuestionServiceClient._read_environment_variables() == ( + False, + "auto", + "foo.com", + ) + + +def test__get_client_cert_source(): + mock_provided_cert_source = mock.Mock() + mock_default_cert_source = mock.Mock() + + assert GenerativeQuestionServiceClient._get_client_cert_source(None, False) is None + assert ( + GenerativeQuestionServiceClient._get_client_cert_source( + mock_provided_cert_source, False + ) + is None + ) + assert ( + GenerativeQuestionServiceClient._get_client_cert_source( + mock_provided_cert_source, True + ) + == mock_provided_cert_source + ) + + with mock.patch( + "google.auth.transport.mtls.has_default_client_cert_source", return_value=True + ): + with mock.patch( + "google.auth.transport.mtls.default_client_cert_source", + return_value=mock_default_cert_source, + ): + assert ( + GenerativeQuestionServiceClient._get_client_cert_source(None, True) + is mock_default_cert_source + ) + assert ( + GenerativeQuestionServiceClient._get_client_cert_source( + mock_provided_cert_source, "true" + ) + is mock_provided_cert_source + ) + + +@mock.patch.object( + GenerativeQuestionServiceClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(GenerativeQuestionServiceClient), +) +@mock.patch.object( + GenerativeQuestionServiceAsyncClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(GenerativeQuestionServiceAsyncClient), +) +def test__get_api_endpoint(): + api_override = "foo.com" + mock_client_cert_source = mock.Mock() + default_universe = GenerativeQuestionServiceClient._DEFAULT_UNIVERSE + default_endpoint = ( + GenerativeQuestionServiceClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=default_universe + ) + ) + mock_universe = "bar.com" + mock_endpoint = GenerativeQuestionServiceClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=mock_universe + ) + + assert ( + GenerativeQuestionServiceClient._get_api_endpoint( + api_override, mock_client_cert_source, default_universe, "always" + ) + == api_override + ) + assert ( + GenerativeQuestionServiceClient._get_api_endpoint( + None, mock_client_cert_source, default_universe, "auto" + ) + == GenerativeQuestionServiceClient.DEFAULT_MTLS_ENDPOINT + ) + assert ( + GenerativeQuestionServiceClient._get_api_endpoint( + None, None, default_universe, "auto" + ) + == default_endpoint + ) + assert ( + GenerativeQuestionServiceClient._get_api_endpoint( + None, None, default_universe, "always" + ) + == GenerativeQuestionServiceClient.DEFAULT_MTLS_ENDPOINT + ) + assert ( + GenerativeQuestionServiceClient._get_api_endpoint( + None, mock_client_cert_source, default_universe, "always" + ) + == GenerativeQuestionServiceClient.DEFAULT_MTLS_ENDPOINT + ) + assert ( + GenerativeQuestionServiceClient._get_api_endpoint( + None, None, mock_universe, "never" + ) + == mock_endpoint + ) + assert ( + GenerativeQuestionServiceClient._get_api_endpoint( + None, None, default_universe, "never" + ) + == default_endpoint + ) + + with pytest.raises(MutualTLSChannelError) as excinfo: + GenerativeQuestionServiceClient._get_api_endpoint( + None, mock_client_cert_source, mock_universe, "auto" + ) + assert ( + str(excinfo.value) + == "mTLS is not supported in any universe other than googleapis.com." + ) + + +def test__get_universe_domain(): + client_universe_domain = "foo.com" + universe_domain_env = "bar.com" + + assert ( + GenerativeQuestionServiceClient._get_universe_domain( + client_universe_domain, universe_domain_env + ) + == client_universe_domain + ) + assert ( + GenerativeQuestionServiceClient._get_universe_domain(None, universe_domain_env) + == universe_domain_env + ) + assert ( + GenerativeQuestionServiceClient._get_universe_domain(None, None) + == GenerativeQuestionServiceClient._DEFAULT_UNIVERSE + ) + + with pytest.raises(ValueError) as excinfo: + GenerativeQuestionServiceClient._get_universe_domain("", None) + assert str(excinfo.value) == "Universe Domain cannot be an empty string." + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name", + [ + ( + GenerativeQuestionServiceClient, + transports.GenerativeQuestionServiceGrpcTransport, + "grpc", + ), + ( + GenerativeQuestionServiceClient, + transports.GenerativeQuestionServiceRestTransport, + "rest", + ), + ], +) +def test__validate_universe_domain(client_class, transport_class, transport_name): + client = client_class( + transport=transport_class(credentials=ga_credentials.AnonymousCredentials()) + ) + assert client._validate_universe_domain() == True + + # Test the case when universe is already validated. + assert client._validate_universe_domain() == True + + if transport_name == "grpc": + # Test the case where credentials are provided by the + # `local_channel_credentials`. The default universes in both match. + channel = grpc.secure_channel( + "http://localhost/", grpc.local_channel_credentials() + ) + client = client_class(transport=transport_class(channel=channel)) + assert client._validate_universe_domain() == True + + # Test the case where credentials do not exist: e.g. a transport is provided + # with no credentials. Validation should still succeed because there is no + # mismatch with non-existent credentials. + channel = grpc.secure_channel( + "http://localhost/", grpc.local_channel_credentials() + ) + transport = transport_class(channel=channel) + transport._credentials = None + client = client_class(transport=transport) + assert client._validate_universe_domain() == True + + # TODO: This is needed to cater for older versions of google-auth + # Make this test unconditional once the minimum supported version of + # google-auth becomes 2.23.0 or higher. + google_auth_major, google_auth_minor = [ + int(part) for part in google.auth.__version__.split(".")[0:2] + ] + if google_auth_major > 2 or (google_auth_major == 2 and google_auth_minor >= 23): + credentials = ga_credentials.AnonymousCredentials() + credentials._universe_domain = "foo.com" + # Test the case when there is a universe mismatch from the credentials. + client = client_class(transport=transport_class(credentials=credentials)) + with pytest.raises(ValueError) as excinfo: + client._validate_universe_domain() + assert ( + str(excinfo.value) + == "The configured universe domain (googleapis.com) does not match the universe domain found in the credentials (foo.com). If you haven't configured the universe domain explicitly, `googleapis.com` is the default." + ) + + # Test the case when there is a universe mismatch from the client. + # + # TODO: Make this test unconditional once the minimum supported version of + # google-api-core becomes 2.15.0 or higher. + api_core_major, api_core_minor = [ + int(part) for part in api_core_version.__version__.split(".")[0:2] + ] + if api_core_major > 2 or (api_core_major == 2 and api_core_minor >= 15): + client = client_class( + client_options={"universe_domain": "bar.com"}, + transport=transport_class( + credentials=ga_credentials.AnonymousCredentials(), + ), + ) + with pytest.raises(ValueError) as excinfo: + client._validate_universe_domain() + assert ( + str(excinfo.value) + == "The configured universe domain (bar.com) does not match the universe domain found in the credentials (googleapis.com). If you haven't configured the universe domain explicitly, `googleapis.com` is the default." + ) + + # Test that ValueError is raised if universe_domain is provided via client options and credentials is None + with pytest.raises(ValueError): + client._compare_universes("foo.bar", None) + + +@pytest.mark.parametrize( + "client_class,transport_name", + [ + (GenerativeQuestionServiceClient, "grpc"), + (GenerativeQuestionServiceAsyncClient, "grpc_asyncio"), + (GenerativeQuestionServiceClient, "rest"), + ], +) +def test_generative_question_service_client_from_service_account_info( + client_class, transport_name +): + creds = ga_credentials.AnonymousCredentials() + with mock.patch.object( + service_account.Credentials, "from_service_account_info" + ) as factory: + factory.return_value = creds + info = {"valid": True} + client = client_class.from_service_account_info(info, transport=transport_name) + assert client.transport._credentials == creds + assert isinstance(client, client_class) + + assert client.transport._host == ( + "retail.googleapis.com:443" + if transport_name in ["grpc", "grpc_asyncio"] + else "https://retail.googleapis.com" + ) + + +@pytest.mark.parametrize( + "transport_class,transport_name", + [ + (transports.GenerativeQuestionServiceGrpcTransport, "grpc"), + (transports.GenerativeQuestionServiceGrpcAsyncIOTransport, "grpc_asyncio"), + (transports.GenerativeQuestionServiceRestTransport, "rest"), + ], +) +def test_generative_question_service_client_service_account_always_use_jwt( + transport_class, transport_name +): + with mock.patch.object( + service_account.Credentials, "with_always_use_jwt_access", create=True + ) as use_jwt: + creds = service_account.Credentials(None, None, None) + transport = transport_class(credentials=creds, always_use_jwt_access=True) + use_jwt.assert_called_once_with(True) + + with mock.patch.object( + service_account.Credentials, "with_always_use_jwt_access", create=True + ) as use_jwt: + creds = service_account.Credentials(None, None, None) + transport = transport_class(credentials=creds, always_use_jwt_access=False) + use_jwt.assert_not_called() + + +@pytest.mark.parametrize( + "client_class,transport_name", + [ + (GenerativeQuestionServiceClient, "grpc"), + (GenerativeQuestionServiceAsyncClient, "grpc_asyncio"), + (GenerativeQuestionServiceClient, "rest"), + ], +) +def test_generative_question_service_client_from_service_account_file( + client_class, transport_name +): + creds = ga_credentials.AnonymousCredentials() + with mock.patch.object( + service_account.Credentials, "from_service_account_file" + ) as factory: + factory.return_value = creds + client = client_class.from_service_account_file( + "dummy/file/path.json", transport=transport_name + ) + assert client.transport._credentials == creds + assert isinstance(client, client_class) + + client = client_class.from_service_account_json( + "dummy/file/path.json", transport=transport_name + ) + assert client.transport._credentials == creds + assert isinstance(client, client_class) + + assert client.transport._host == ( + "retail.googleapis.com:443" + if transport_name in ["grpc", "grpc_asyncio"] + else "https://retail.googleapis.com" + ) + + +def test_generative_question_service_client_get_transport_class(): + transport = GenerativeQuestionServiceClient.get_transport_class() + available_transports = [ + transports.GenerativeQuestionServiceGrpcTransport, + transports.GenerativeQuestionServiceRestTransport, + ] + assert transport in available_transports + + transport = GenerativeQuestionServiceClient.get_transport_class("grpc") + assert transport == transports.GenerativeQuestionServiceGrpcTransport + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name", + [ + ( + GenerativeQuestionServiceClient, + transports.GenerativeQuestionServiceGrpcTransport, + "grpc", + ), + ( + GenerativeQuestionServiceAsyncClient, + transports.GenerativeQuestionServiceGrpcAsyncIOTransport, + "grpc_asyncio", + ), + ( + GenerativeQuestionServiceClient, + transports.GenerativeQuestionServiceRestTransport, + "rest", + ), + ], +) +@mock.patch.object( + GenerativeQuestionServiceClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(GenerativeQuestionServiceClient), +) +@mock.patch.object( + GenerativeQuestionServiceAsyncClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(GenerativeQuestionServiceAsyncClient), +) +def test_generative_question_service_client_client_options( + client_class, transport_class, transport_name +): + # Check that if channel is provided we won't create a new one. + with mock.patch.object( + GenerativeQuestionServiceClient, "get_transport_class" + ) as gtc: + transport = transport_class(credentials=ga_credentials.AnonymousCredentials()) + client = client_class(transport=transport) + gtc.assert_not_called() + + # Check that if channel is provided via str we will create a new one. + with mock.patch.object( + GenerativeQuestionServiceClient, "get_transport_class" + ) as gtc: + client = client_class(transport=transport_name) + gtc.assert_called() + + # Check the case api_endpoint is provided. + options = client_options.ClientOptions(api_endpoint="squid.clam.whelk") + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(transport=transport_name, client_options=options) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host="squid.clam.whelk", + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT is + # "never". + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT is + # "always". + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client.DEFAULT_MTLS_ENDPOINT, + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT has + # unsupported value. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "Unsupported"}): + with pytest.raises(MutualTLSChannelError) as excinfo: + client = client_class(transport=transport_name) + assert ( + str(excinfo.value) + == "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`" + ) + + # Check the case GOOGLE_API_USE_CLIENT_CERTIFICATE has unsupported value. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"} + ): + with pytest.raises(ValueError) as excinfo: + client = client_class(transport=transport_name) + assert ( + str(excinfo.value) + == "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + + # Check the case quota_project_id is provided + options = client_options.ClientOptions(quota_project_id="octopus") + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options, transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id="octopus", + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + # Check the case api_endpoint is provided + options = client_options.ClientOptions( + api_audience="https://language.googleapis.com" + ) + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options, transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience="https://language.googleapis.com", + ) + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name,use_client_cert_env", + [ + ( + GenerativeQuestionServiceClient, + transports.GenerativeQuestionServiceGrpcTransport, + "grpc", + "true", + ), + ( + GenerativeQuestionServiceAsyncClient, + transports.GenerativeQuestionServiceGrpcAsyncIOTransport, + "grpc_asyncio", + "true", + ), + ( + GenerativeQuestionServiceClient, + transports.GenerativeQuestionServiceGrpcTransport, + "grpc", + "false", + ), + ( + GenerativeQuestionServiceAsyncClient, + transports.GenerativeQuestionServiceGrpcAsyncIOTransport, + "grpc_asyncio", + "false", + ), + ( + GenerativeQuestionServiceClient, + transports.GenerativeQuestionServiceRestTransport, + "rest", + "true", + ), + ( + GenerativeQuestionServiceClient, + transports.GenerativeQuestionServiceRestTransport, + "rest", + "false", + ), + ], +) +@mock.patch.object( + GenerativeQuestionServiceClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(GenerativeQuestionServiceClient), +) +@mock.patch.object( + GenerativeQuestionServiceAsyncClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(GenerativeQuestionServiceAsyncClient), +) +@mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "auto"}) +def test_generative_question_service_client_mtls_env_auto( + client_class, transport_class, transport_name, use_client_cert_env +): + # This tests the endpoint autoswitch behavior. Endpoint is autoswitched to the default + # mtls endpoint, if GOOGLE_API_USE_CLIENT_CERTIFICATE is "true" and client cert exists. + + # Check the case client_cert_source is provided. Whether client cert is used depends on + # GOOGLE_API_USE_CLIENT_CERTIFICATE value. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": use_client_cert_env} + ): + options = client_options.ClientOptions( + client_cert_source=client_cert_source_callback + ) + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options, transport=transport_name) + + if use_client_cert_env == "false": + expected_client_cert_source = None + expected_host = client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ) + else: + expected_client_cert_source = client_cert_source_callback + expected_host = client.DEFAULT_MTLS_ENDPOINT + + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=expected_host, + scopes=None, + client_cert_source_for_mtls=expected_client_cert_source, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + # Check the case ADC client cert is provided. Whether client cert is used depends on + # GOOGLE_API_USE_CLIENT_CERTIFICATE value. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": use_client_cert_env} + ): + with mock.patch.object(transport_class, "__init__") as patched: + with mock.patch( + "google.auth.transport.mtls.has_default_client_cert_source", + return_value=True, + ): + with mock.patch( + "google.auth.transport.mtls.default_client_cert_source", + return_value=client_cert_source_callback, + ): + if use_client_cert_env == "false": + expected_host = client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ) + expected_client_cert_source = None + else: + expected_host = client.DEFAULT_MTLS_ENDPOINT + expected_client_cert_source = client_cert_source_callback + + patched.return_value = None + client = client_class(transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=expected_host, + scopes=None, + client_cert_source_for_mtls=expected_client_cert_source, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + # Check the case client_cert_source and ADC client cert are not provided. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": use_client_cert_env} + ): + with mock.patch.object(transport_class, "__init__") as patched: + with mock.patch( + "google.auth.transport.mtls.has_default_client_cert_source", + return_value=False, + ): + patched.return_value = None + client = client_class(transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + +@pytest.mark.parametrize( + "client_class", + [GenerativeQuestionServiceClient, GenerativeQuestionServiceAsyncClient], +) +@mock.patch.object( + GenerativeQuestionServiceClient, + "DEFAULT_ENDPOINT", + modify_default_endpoint(GenerativeQuestionServiceClient), +) +@mock.patch.object( + GenerativeQuestionServiceAsyncClient, + "DEFAULT_ENDPOINT", + modify_default_endpoint(GenerativeQuestionServiceAsyncClient), +) +def test_generative_question_service_client_get_mtls_endpoint_and_cert_source( + client_class, +): + mock_client_cert_source = mock.Mock() + + # Test the case GOOGLE_API_USE_CLIENT_CERTIFICATE is "true". + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "true"}): + mock_api_endpoint = "foo" + options = client_options.ClientOptions( + client_cert_source=mock_client_cert_source, api_endpoint=mock_api_endpoint + ) + api_endpoint, cert_source = client_class.get_mtls_endpoint_and_cert_source( + options + ) + assert api_endpoint == mock_api_endpoint + assert cert_source == mock_client_cert_source + + # Test the case GOOGLE_API_USE_CLIENT_CERTIFICATE is "false". + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "false"}): + mock_client_cert_source = mock.Mock() + mock_api_endpoint = "foo" + options = client_options.ClientOptions( + client_cert_source=mock_client_cert_source, api_endpoint=mock_api_endpoint + ) + api_endpoint, cert_source = client_class.get_mtls_endpoint_and_cert_source( + options + ) + assert api_endpoint == mock_api_endpoint + assert cert_source is None + + # Test the case GOOGLE_API_USE_MTLS_ENDPOINT is "never". + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): + api_endpoint, cert_source = client_class.get_mtls_endpoint_and_cert_source() + assert api_endpoint == client_class.DEFAULT_ENDPOINT + assert cert_source is None + + # Test the case GOOGLE_API_USE_MTLS_ENDPOINT is "always". + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): + api_endpoint, cert_source = client_class.get_mtls_endpoint_and_cert_source() + assert api_endpoint == client_class.DEFAULT_MTLS_ENDPOINT + assert cert_source is None + + # Test the case GOOGLE_API_USE_MTLS_ENDPOINT is "auto" and default cert doesn't exist. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "true"}): + with mock.patch( + "google.auth.transport.mtls.has_default_client_cert_source", + return_value=False, + ): + api_endpoint, cert_source = client_class.get_mtls_endpoint_and_cert_source() + assert api_endpoint == client_class.DEFAULT_ENDPOINT + assert cert_source is None + + # Test the case GOOGLE_API_USE_MTLS_ENDPOINT is "auto" and default cert exists. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "true"}): + with mock.patch( + "google.auth.transport.mtls.has_default_client_cert_source", + return_value=True, + ): + with mock.patch( + "google.auth.transport.mtls.default_client_cert_source", + return_value=mock_client_cert_source, + ): + ( + api_endpoint, + cert_source, + ) = client_class.get_mtls_endpoint_and_cert_source() + assert api_endpoint == client_class.DEFAULT_MTLS_ENDPOINT + assert cert_source == mock_client_cert_source + + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT has + # unsupported value. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "Unsupported"}): + with pytest.raises(MutualTLSChannelError) as excinfo: + client_class.get_mtls_endpoint_and_cert_source() + + assert ( + str(excinfo.value) + == "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`" + ) + + # Check the case GOOGLE_API_USE_CLIENT_CERTIFICATE has unsupported value. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"} + ): + with pytest.raises(ValueError) as excinfo: + client_class.get_mtls_endpoint_and_cert_source() + + assert ( + str(excinfo.value) + == "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + + +@pytest.mark.parametrize( + "client_class", + [GenerativeQuestionServiceClient, GenerativeQuestionServiceAsyncClient], +) +@mock.patch.object( + GenerativeQuestionServiceClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(GenerativeQuestionServiceClient), +) +@mock.patch.object( + GenerativeQuestionServiceAsyncClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(GenerativeQuestionServiceAsyncClient), +) +def test_generative_question_service_client_client_api_endpoint(client_class): + mock_client_cert_source = client_cert_source_callback + api_override = "foo.com" + default_universe = GenerativeQuestionServiceClient._DEFAULT_UNIVERSE + default_endpoint = ( + GenerativeQuestionServiceClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=default_universe + ) + ) + mock_universe = "bar.com" + mock_endpoint = GenerativeQuestionServiceClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=mock_universe + ) + + # If ClientOptions.api_endpoint is set and GOOGLE_API_USE_CLIENT_CERTIFICATE="true", + # use ClientOptions.api_endpoint as the api endpoint regardless. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "true"}): + with mock.patch( + "google.auth.transport.requests.AuthorizedSession.configure_mtls_channel" + ): + options = client_options.ClientOptions( + client_cert_source=mock_client_cert_source, api_endpoint=api_override + ) + client = client_class( + client_options=options, + credentials=ga_credentials.AnonymousCredentials(), + ) + assert client.api_endpoint == api_override + + # If ClientOptions.api_endpoint is not set and GOOGLE_API_USE_MTLS_ENDPOINT="never", + # use the _DEFAULT_ENDPOINT_TEMPLATE populated with GDU as the api endpoint. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): + client = client_class(credentials=ga_credentials.AnonymousCredentials()) + assert client.api_endpoint == default_endpoint + + # If ClientOptions.api_endpoint is not set and GOOGLE_API_USE_MTLS_ENDPOINT="always", + # use the DEFAULT_MTLS_ENDPOINT as the api endpoint. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): + client = client_class(credentials=ga_credentials.AnonymousCredentials()) + assert client.api_endpoint == client_class.DEFAULT_MTLS_ENDPOINT + + # If ClientOptions.api_endpoint is not set, GOOGLE_API_USE_MTLS_ENDPOINT="auto" (default), + # GOOGLE_API_USE_CLIENT_CERTIFICATE="false" (default), default cert source doesn't exist, + # and ClientOptions.universe_domain="bar.com", + # use the _DEFAULT_ENDPOINT_TEMPLATE populated with universe domain as the api endpoint. + options = client_options.ClientOptions() + universe_exists = hasattr(options, "universe_domain") + if universe_exists: + options = client_options.ClientOptions(universe_domain=mock_universe) + client = client_class( + client_options=options, credentials=ga_credentials.AnonymousCredentials() + ) + else: + client = client_class( + client_options=options, credentials=ga_credentials.AnonymousCredentials() + ) + assert client.api_endpoint == ( + mock_endpoint if universe_exists else default_endpoint + ) + assert client.universe_domain == ( + mock_universe if universe_exists else default_universe + ) + + # If ClientOptions does not have a universe domain attribute and GOOGLE_API_USE_MTLS_ENDPOINT="never", + # use the _DEFAULT_ENDPOINT_TEMPLATE populated with GDU as the api endpoint. + options = client_options.ClientOptions() + if hasattr(options, "universe_domain"): + delattr(options, "universe_domain") + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): + client = client_class( + client_options=options, credentials=ga_credentials.AnonymousCredentials() + ) + assert client.api_endpoint == default_endpoint + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name", + [ + ( + GenerativeQuestionServiceClient, + transports.GenerativeQuestionServiceGrpcTransport, + "grpc", + ), + ( + GenerativeQuestionServiceAsyncClient, + transports.GenerativeQuestionServiceGrpcAsyncIOTransport, + "grpc_asyncio", + ), + ( + GenerativeQuestionServiceClient, + transports.GenerativeQuestionServiceRestTransport, + "rest", + ), + ], +) +def test_generative_question_service_client_client_options_scopes( + client_class, transport_class, transport_name +): + # Check the case scopes are provided. + options = client_options.ClientOptions( + scopes=["1", "2"], + ) + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options, transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), + scopes=["1", "2"], + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name,grpc_helpers", + [ + ( + GenerativeQuestionServiceClient, + transports.GenerativeQuestionServiceGrpcTransport, + "grpc", + grpc_helpers, + ), + ( + GenerativeQuestionServiceAsyncClient, + transports.GenerativeQuestionServiceGrpcAsyncIOTransport, + "grpc_asyncio", + grpc_helpers_async, + ), + ( + GenerativeQuestionServiceClient, + transports.GenerativeQuestionServiceRestTransport, + "rest", + None, + ), + ], +) +def test_generative_question_service_client_client_options_credentials_file( + client_class, transport_class, transport_name, grpc_helpers +): + # Check the case credentials file is provided. + options = client_options.ClientOptions(credentials_file="credentials.json") + + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options, transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file="credentials.json", + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + +def test_generative_question_service_client_client_options_from_dict(): + with mock.patch( + "google.cloud.retail_v2.services.generative_question_service.transports.GenerativeQuestionServiceGrpcTransport.__init__" + ) as grpc_transport: + grpc_transport.return_value = None + client = GenerativeQuestionServiceClient( + client_options={"api_endpoint": "squid.clam.whelk"} + ) + grpc_transport.assert_called_once_with( + credentials=None, + credentials_file=None, + host="squid.clam.whelk", + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name,grpc_helpers", + [ + ( + GenerativeQuestionServiceClient, + transports.GenerativeQuestionServiceGrpcTransport, + "grpc", + grpc_helpers, + ), + ( + GenerativeQuestionServiceAsyncClient, + transports.GenerativeQuestionServiceGrpcAsyncIOTransport, + "grpc_asyncio", + grpc_helpers_async, + ), + ], +) +def test_generative_question_service_client_create_channel_credentials_file( + client_class, transport_class, transport_name, grpc_helpers +): + # Check the case credentials file is provided. + options = client_options.ClientOptions(credentials_file="credentials.json") + + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options, transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file="credentials.json", + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + # test that the credentials from file are saved and used as the credentials. + with mock.patch.object( + google.auth, "load_credentials_from_file", autospec=True + ) as load_creds, mock.patch.object( + google.auth, "default", autospec=True + ) as adc, mock.patch.object( + grpc_helpers, "create_channel" + ) as create_channel: + creds = ga_credentials.AnonymousCredentials() + file_creds = ga_credentials.AnonymousCredentials() + load_creds.return_value = (file_creds, None) + adc.return_value = (creds, None) + client = client_class(client_options=options, transport=transport_name) + create_channel.assert_called_with( + "retail.googleapis.com:443", + credentials=file_creds, + credentials_file=None, + quota_project_id=None, + default_scopes=("https://www.googleapis.com/auth/cloud-platform",), + scopes=None, + default_host="retail.googleapis.com", + ssl_credentials=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + +@pytest.mark.parametrize( + "request_type", + [ + generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest, + dict, + ], +) +def test_update_generative_questions_feature_config( + request_type, transport: str = "grpc" +): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_questions_feature_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = generative_question.GenerativeQuestionsFeatureConfig( + catalog="catalog_value", + feature_enabled=True, + minimum_products=1743, + ) + response = client.update_generative_questions_feature_config(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = ( + generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest() + ) + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, generative_question.GenerativeQuestionsFeatureConfig) + assert response.catalog == "catalog_value" + assert response.feature_enabled is True + assert response.minimum_products == 1743 + + +def test_update_generative_questions_feature_config_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_questions_feature_config), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.update_generative_questions_feature_config() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert ( + args[0] + == generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest() + ) + + +def test_update_generative_questions_feature_config_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = ( + generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest() + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_questions_feature_config), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.update_generative_questions_feature_config(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert ( + args[0] + == generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest() + ) + + +def test_update_generative_questions_feature_config_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.update_generative_questions_feature_config + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.update_generative_questions_feature_config + ] = mock_rpc + request = {} + client.update_generative_questions_feature_config(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.update_generative_questions_feature_config(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_update_generative_questions_feature_config_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_questions_feature_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question.GenerativeQuestionsFeatureConfig( + catalog="catalog_value", + feature_enabled=True, + minimum_products=1743, + ) + ) + response = await client.update_generative_questions_feature_config() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert ( + args[0] + == generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest() + ) + + +@pytest.mark.asyncio +async def test_update_generative_questions_feature_config_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.update_generative_questions_feature_config + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.AsyncMock() + mock_rpc.return_value = mock.Mock() + client._client._transport._wrapped_methods[ + client._client._transport.update_generative_questions_feature_config + ] = mock_rpc + + request = {} + await client.update_generative_questions_feature_config(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + await client.update_generative_questions_feature_config(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_update_generative_questions_feature_config_async( + transport: str = "grpc_asyncio", + request_type=generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest, +): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_questions_feature_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question.GenerativeQuestionsFeatureConfig( + catalog="catalog_value", + feature_enabled=True, + minimum_products=1743, + ) + ) + response = await client.update_generative_questions_feature_config(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = ( + generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest() + ) + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, generative_question.GenerativeQuestionsFeatureConfig) + assert response.catalog == "catalog_value" + assert response.feature_enabled is True + assert response.minimum_products == 1743 + + +@pytest.mark.asyncio +async def test_update_generative_questions_feature_config_async_from_dict(): + await test_update_generative_questions_feature_config_async(request_type=dict) + + +def test_update_generative_questions_feature_config_field_headers(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = ( + generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest() + ) + + request.generative_questions_feature_config.catalog = "catalog_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_questions_feature_config), "__call__" + ) as call: + call.return_value = generative_question.GenerativeQuestionsFeatureConfig() + client.update_generative_questions_feature_config(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "generative_questions_feature_config.catalog=catalog_value", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_update_generative_questions_feature_config_field_headers_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = ( + generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest() + ) + + request.generative_questions_feature_config.catalog = "catalog_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_questions_feature_config), "__call__" + ) as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question.GenerativeQuestionsFeatureConfig() + ) + await client.update_generative_questions_feature_config(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "generative_questions_feature_config.catalog=catalog_value", + ) in kw["metadata"] + + +def test_update_generative_questions_feature_config_flattened(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_questions_feature_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = generative_question.GenerativeQuestionsFeatureConfig() + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.update_generative_questions_feature_config( + generative_questions_feature_config=generative_question.GenerativeQuestionsFeatureConfig( + catalog="catalog_value" + ), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + arg = args[0].generative_questions_feature_config + mock_val = generative_question.GenerativeQuestionsFeatureConfig( + catalog="catalog_value" + ) + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val + + +def test_update_generative_questions_feature_config_flattened_error(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.update_generative_questions_feature_config( + generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest(), + generative_questions_feature_config=generative_question.GenerativeQuestionsFeatureConfig( + catalog="catalog_value" + ), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + +@pytest.mark.asyncio +async def test_update_generative_questions_feature_config_flattened_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_questions_feature_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = generative_question.GenerativeQuestionsFeatureConfig() + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question.GenerativeQuestionsFeatureConfig() + ) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.update_generative_questions_feature_config( + generative_questions_feature_config=generative_question.GenerativeQuestionsFeatureConfig( + catalog="catalog_value" + ), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + arg = args[0].generative_questions_feature_config + mock_val = generative_question.GenerativeQuestionsFeatureConfig( + catalog="catalog_value" + ) + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val + + +@pytest.mark.asyncio +async def test_update_generative_questions_feature_config_flattened_error_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + await client.update_generative_questions_feature_config( + generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest(), + generative_questions_feature_config=generative_question.GenerativeQuestionsFeatureConfig( + catalog="catalog_value" + ), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + +@pytest.mark.parametrize( + "request_type", + [ + generative_question_service.GetGenerativeQuestionsFeatureConfigRequest, + dict, + ], +) +def test_get_generative_questions_feature_config(request_type, transport: str = "grpc"): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.get_generative_questions_feature_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = generative_question.GenerativeQuestionsFeatureConfig( + catalog="catalog_value", + feature_enabled=True, + minimum_products=1743, + ) + response = client.get_generative_questions_feature_config(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = ( + generative_question_service.GetGenerativeQuestionsFeatureConfigRequest() + ) + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, generative_question.GenerativeQuestionsFeatureConfig) + assert response.catalog == "catalog_value" + assert response.feature_enabled is True + assert response.minimum_products == 1743 + + +def test_get_generative_questions_feature_config_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.get_generative_questions_feature_config), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.get_generative_questions_feature_config() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert ( + args[0] + == generative_question_service.GetGenerativeQuestionsFeatureConfigRequest() + ) + + +def test_get_generative_questions_feature_config_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = generative_question_service.GetGenerativeQuestionsFeatureConfigRequest( + catalog="catalog_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.get_generative_questions_feature_config), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.get_generative_questions_feature_config(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[ + 0 + ] == generative_question_service.GetGenerativeQuestionsFeatureConfigRequest( + catalog="catalog_value", + ) + + +def test_get_generative_questions_feature_config_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.get_generative_questions_feature_config + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.get_generative_questions_feature_config + ] = mock_rpc + request = {} + client.get_generative_questions_feature_config(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.get_generative_questions_feature_config(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_get_generative_questions_feature_config_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.get_generative_questions_feature_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question.GenerativeQuestionsFeatureConfig( + catalog="catalog_value", + feature_enabled=True, + minimum_products=1743, + ) + ) + response = await client.get_generative_questions_feature_config() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert ( + args[0] + == generative_question_service.GetGenerativeQuestionsFeatureConfigRequest() + ) + + +@pytest.mark.asyncio +async def test_get_generative_questions_feature_config_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.get_generative_questions_feature_config + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.AsyncMock() + mock_rpc.return_value = mock.Mock() + client._client._transport._wrapped_methods[ + client._client._transport.get_generative_questions_feature_config + ] = mock_rpc + + request = {} + await client.get_generative_questions_feature_config(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + await client.get_generative_questions_feature_config(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_get_generative_questions_feature_config_async( + transport: str = "grpc_asyncio", + request_type=generative_question_service.GetGenerativeQuestionsFeatureConfigRequest, +): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.get_generative_questions_feature_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question.GenerativeQuestionsFeatureConfig( + catalog="catalog_value", + feature_enabled=True, + minimum_products=1743, + ) + ) + response = await client.get_generative_questions_feature_config(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = ( + generative_question_service.GetGenerativeQuestionsFeatureConfigRequest() + ) + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, generative_question.GenerativeQuestionsFeatureConfig) + assert response.catalog == "catalog_value" + assert response.feature_enabled is True + assert response.minimum_products == 1743 + + +@pytest.mark.asyncio +async def test_get_generative_questions_feature_config_async_from_dict(): + await test_get_generative_questions_feature_config_async(request_type=dict) + + +def test_get_generative_questions_feature_config_field_headers(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = generative_question_service.GetGenerativeQuestionsFeatureConfigRequest() + + request.catalog = "catalog_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.get_generative_questions_feature_config), "__call__" + ) as call: + call.return_value = generative_question.GenerativeQuestionsFeatureConfig() + client.get_generative_questions_feature_config(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "catalog=catalog_value", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_get_generative_questions_feature_config_field_headers_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = generative_question_service.GetGenerativeQuestionsFeatureConfigRequest() + + request.catalog = "catalog_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.get_generative_questions_feature_config), "__call__" + ) as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question.GenerativeQuestionsFeatureConfig() + ) + await client.get_generative_questions_feature_config(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "catalog=catalog_value", + ) in kw["metadata"] + + +def test_get_generative_questions_feature_config_flattened(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.get_generative_questions_feature_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = generative_question.GenerativeQuestionsFeatureConfig() + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.get_generative_questions_feature_config( + catalog="catalog_value", + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + arg = args[0].catalog + mock_val = "catalog_value" + assert arg == mock_val + + +def test_get_generative_questions_feature_config_flattened_error(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.get_generative_questions_feature_config( + generative_question_service.GetGenerativeQuestionsFeatureConfigRequest(), + catalog="catalog_value", + ) + + +@pytest.mark.asyncio +async def test_get_generative_questions_feature_config_flattened_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.get_generative_questions_feature_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = generative_question.GenerativeQuestionsFeatureConfig() + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question.GenerativeQuestionsFeatureConfig() + ) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.get_generative_questions_feature_config( + catalog="catalog_value", + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + arg = args[0].catalog + mock_val = "catalog_value" + assert arg == mock_val + + +@pytest.mark.asyncio +async def test_get_generative_questions_feature_config_flattened_error_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + await client.get_generative_questions_feature_config( + generative_question_service.GetGenerativeQuestionsFeatureConfigRequest(), + catalog="catalog_value", + ) + + +@pytest.mark.parametrize( + "request_type", + [ + generative_question_service.ListGenerativeQuestionConfigsRequest, + dict, + ], +) +def test_list_generative_question_configs(request_type, transport: str = "grpc"): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_generative_question_configs), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = ( + generative_question_service.ListGenerativeQuestionConfigsResponse() + ) + response = client.list_generative_question_configs(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = generative_question_service.ListGenerativeQuestionConfigsRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance( + response, generative_question_service.ListGenerativeQuestionConfigsResponse + ) + + +def test_list_generative_question_configs_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_generative_question_configs), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.list_generative_question_configs() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert ( + args[0] + == generative_question_service.ListGenerativeQuestionConfigsRequest() + ) + + +def test_list_generative_question_configs_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = generative_question_service.ListGenerativeQuestionConfigsRequest( + parent="parent_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_generative_question_configs), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.list_generative_question_configs(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[ + 0 + ] == generative_question_service.ListGenerativeQuestionConfigsRequest( + parent="parent_value", + ) + + +def test_list_generative_question_configs_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.list_generative_question_configs + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.list_generative_question_configs + ] = mock_rpc + request = {} + client.list_generative_question_configs(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.list_generative_question_configs(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_list_generative_question_configs_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_generative_question_configs), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question_service.ListGenerativeQuestionConfigsResponse() + ) + response = await client.list_generative_question_configs() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert ( + args[0] + == generative_question_service.ListGenerativeQuestionConfigsRequest() + ) + + +@pytest.mark.asyncio +async def test_list_generative_question_configs_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.list_generative_question_configs + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.AsyncMock() + mock_rpc.return_value = mock.Mock() + client._client._transport._wrapped_methods[ + client._client._transport.list_generative_question_configs + ] = mock_rpc + + request = {} + await client.list_generative_question_configs(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + await client.list_generative_question_configs(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_list_generative_question_configs_async( + transport: str = "grpc_asyncio", + request_type=generative_question_service.ListGenerativeQuestionConfigsRequest, +): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_generative_question_configs), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question_service.ListGenerativeQuestionConfigsResponse() + ) + response = await client.list_generative_question_configs(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = generative_question_service.ListGenerativeQuestionConfigsRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance( + response, generative_question_service.ListGenerativeQuestionConfigsResponse + ) + + +@pytest.mark.asyncio +async def test_list_generative_question_configs_async_from_dict(): + await test_list_generative_question_configs_async(request_type=dict) + + +def test_list_generative_question_configs_field_headers(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = generative_question_service.ListGenerativeQuestionConfigsRequest() + + request.parent = "parent_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_generative_question_configs), "__call__" + ) as call: + call.return_value = ( + generative_question_service.ListGenerativeQuestionConfigsResponse() + ) + client.list_generative_question_configs(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "parent=parent_value", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_list_generative_question_configs_field_headers_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = generative_question_service.ListGenerativeQuestionConfigsRequest() + + request.parent = "parent_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_generative_question_configs), "__call__" + ) as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question_service.ListGenerativeQuestionConfigsResponse() + ) + await client.list_generative_question_configs(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "parent=parent_value", + ) in kw["metadata"] + + +def test_list_generative_question_configs_flattened(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_generative_question_configs), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = ( + generative_question_service.ListGenerativeQuestionConfigsResponse() + ) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.list_generative_question_configs( + parent="parent_value", + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + + +def test_list_generative_question_configs_flattened_error(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.list_generative_question_configs( + generative_question_service.ListGenerativeQuestionConfigsRequest(), + parent="parent_value", + ) + + +@pytest.mark.asyncio +async def test_list_generative_question_configs_flattened_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_generative_question_configs), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = ( + generative_question_service.ListGenerativeQuestionConfigsResponse() + ) + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question_service.ListGenerativeQuestionConfigsResponse() + ) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.list_generative_question_configs( + parent="parent_value", + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + + +@pytest.mark.asyncio +async def test_list_generative_question_configs_flattened_error_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + await client.list_generative_question_configs( + generative_question_service.ListGenerativeQuestionConfigsRequest(), + parent="parent_value", + ) + + +@pytest.mark.parametrize( + "request_type", + [ + generative_question_service.UpdateGenerativeQuestionConfigRequest, + dict, + ], +) +def test_update_generative_question_config(request_type, transport: str = "grpc"): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_question_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = generative_question.GenerativeQuestionConfig( + catalog="catalog_value", + facet="facet_value", + generated_question="generated_question_value", + final_question="final_question_value", + example_values=["example_values_value"], + frequency=0.978, + allowed_in_conversation=True, + ) + response = client.update_generative_question_config(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = generative_question_service.UpdateGenerativeQuestionConfigRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, generative_question.GenerativeQuestionConfig) + assert response.catalog == "catalog_value" + assert response.facet == "facet_value" + assert response.generated_question == "generated_question_value" + assert response.final_question == "final_question_value" + assert response.example_values == ["example_values_value"] + assert math.isclose(response.frequency, 0.978, rel_tol=1e-6) + assert response.allowed_in_conversation is True + + +def test_update_generative_question_config_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_question_config), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.update_generative_question_config() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert ( + args[0] + == generative_question_service.UpdateGenerativeQuestionConfigRequest() + ) + + +def test_update_generative_question_config_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = generative_question_service.UpdateGenerativeQuestionConfigRequest() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_question_config), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.update_generative_question_config(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert ( + args[0] + == generative_question_service.UpdateGenerativeQuestionConfigRequest() + ) + + +def test_update_generative_question_config_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.update_generative_question_config + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.update_generative_question_config + ] = mock_rpc + request = {} + client.update_generative_question_config(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.update_generative_question_config(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_update_generative_question_config_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_question_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question.GenerativeQuestionConfig( + catalog="catalog_value", + facet="facet_value", + generated_question="generated_question_value", + final_question="final_question_value", + example_values=["example_values_value"], + frequency=0.978, + allowed_in_conversation=True, + ) + ) + response = await client.update_generative_question_config() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert ( + args[0] + == generative_question_service.UpdateGenerativeQuestionConfigRequest() + ) + + +@pytest.mark.asyncio +async def test_update_generative_question_config_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.update_generative_question_config + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.AsyncMock() + mock_rpc.return_value = mock.Mock() + client._client._transport._wrapped_methods[ + client._client._transport.update_generative_question_config + ] = mock_rpc + + request = {} + await client.update_generative_question_config(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + await client.update_generative_question_config(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_update_generative_question_config_async( + transport: str = "grpc_asyncio", + request_type=generative_question_service.UpdateGenerativeQuestionConfigRequest, +): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_question_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question.GenerativeQuestionConfig( + catalog="catalog_value", + facet="facet_value", + generated_question="generated_question_value", + final_question="final_question_value", + example_values=["example_values_value"], + frequency=0.978, + allowed_in_conversation=True, + ) + ) + response = await client.update_generative_question_config(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = generative_question_service.UpdateGenerativeQuestionConfigRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, generative_question.GenerativeQuestionConfig) + assert response.catalog == "catalog_value" + assert response.facet == "facet_value" + assert response.generated_question == "generated_question_value" + assert response.final_question == "final_question_value" + assert response.example_values == ["example_values_value"] + assert math.isclose(response.frequency, 0.978, rel_tol=1e-6) + assert response.allowed_in_conversation is True + + +@pytest.mark.asyncio +async def test_update_generative_question_config_async_from_dict(): + await test_update_generative_question_config_async(request_type=dict) + + +def test_update_generative_question_config_field_headers(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = generative_question_service.UpdateGenerativeQuestionConfigRequest() + + request.generative_question_config.catalog = "catalog_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_question_config), "__call__" + ) as call: + call.return_value = generative_question.GenerativeQuestionConfig() + client.update_generative_question_config(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "generative_question_config.catalog=catalog_value", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_update_generative_question_config_field_headers_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = generative_question_service.UpdateGenerativeQuestionConfigRequest() + + request.generative_question_config.catalog = "catalog_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_question_config), "__call__" + ) as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question.GenerativeQuestionConfig() + ) + await client.update_generative_question_config(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "generative_question_config.catalog=catalog_value", + ) in kw["metadata"] + + +def test_update_generative_question_config_flattened(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_question_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = generative_question.GenerativeQuestionConfig() + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.update_generative_question_config( + generative_question_config=generative_question.GenerativeQuestionConfig( + catalog="catalog_value" + ), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + arg = args[0].generative_question_config + mock_val = generative_question.GenerativeQuestionConfig(catalog="catalog_value") + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val + + +def test_update_generative_question_config_flattened_error(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.update_generative_question_config( + generative_question_service.UpdateGenerativeQuestionConfigRequest(), + generative_question_config=generative_question.GenerativeQuestionConfig( + catalog="catalog_value" + ), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + +@pytest.mark.asyncio +async def test_update_generative_question_config_flattened_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_question_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = generative_question.GenerativeQuestionConfig() + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question.GenerativeQuestionConfig() + ) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.update_generative_question_config( + generative_question_config=generative_question.GenerativeQuestionConfig( + catalog="catalog_value" + ), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + arg = args[0].generative_question_config + mock_val = generative_question.GenerativeQuestionConfig(catalog="catalog_value") + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val + + +@pytest.mark.asyncio +async def test_update_generative_question_config_flattened_error_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + await client.update_generative_question_config( + generative_question_service.UpdateGenerativeQuestionConfigRequest(), + generative_question_config=generative_question.GenerativeQuestionConfig( + catalog="catalog_value" + ), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + +@pytest.mark.parametrize( + "request_type", + [ + generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest, + dict, + ], +) +def test_batch_update_generative_question_configs( + request_type, transport: str = "grpc" +): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.batch_update_generative_question_configs), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = ( + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse() + ) + response = client.batch_update_generative_question_configs(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = ( + generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest() + ) + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance( + response, + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse, + ) + + +def test_batch_update_generative_question_configs_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.batch_update_generative_question_configs), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.batch_update_generative_question_configs() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert ( + args[0] + == generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest() + ) + + +def test_batch_update_generative_question_configs_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest( + parent="parent_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.batch_update_generative_question_configs), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.batch_update_generative_question_configs(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[ + 0 + ] == generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest( + parent="parent_value", + ) + + +def test_batch_update_generative_question_configs_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.batch_update_generative_question_configs + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.batch_update_generative_question_configs + ] = mock_rpc + request = {} + client.batch_update_generative_question_configs(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.batch_update_generative_question_configs(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_batch_update_generative_question_configs_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.batch_update_generative_question_configs), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse() + ) + response = await client.batch_update_generative_question_configs() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert ( + args[0] + == generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest() + ) + + +@pytest.mark.asyncio +async def test_batch_update_generative_question_configs_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.batch_update_generative_question_configs + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.AsyncMock() + mock_rpc.return_value = mock.Mock() + client._client._transport._wrapped_methods[ + client._client._transport.batch_update_generative_question_configs + ] = mock_rpc + + request = {} + await client.batch_update_generative_question_configs(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + await client.batch_update_generative_question_configs(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_batch_update_generative_question_configs_async( + transport: str = "grpc_asyncio", + request_type=generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest, +): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.batch_update_generative_question_configs), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse() + ) + response = await client.batch_update_generative_question_configs(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = ( + generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest() + ) + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance( + response, + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse, + ) + + +@pytest.mark.asyncio +async def test_batch_update_generative_question_configs_async_from_dict(): + await test_batch_update_generative_question_configs_async(request_type=dict) + + +def test_batch_update_generative_question_configs_field_headers(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest() + + request.parent = "parent_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.batch_update_generative_question_configs), "__call__" + ) as call: + call.return_value = ( + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse() + ) + client.batch_update_generative_question_configs(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "parent=parent_value", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_batch_update_generative_question_configs_field_headers_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest() + + request.parent = "parent_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.batch_update_generative_question_configs), "__call__" + ) as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse() + ) + await client.batch_update_generative_question_configs(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "parent=parent_value", + ) in kw["metadata"] + + +def test_batch_update_generative_question_configs_flattened(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.batch_update_generative_question_configs), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = ( + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse() + ) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.batch_update_generative_question_configs( + parent="parent_value", + requests=[ + generative_question_service.UpdateGenerativeQuestionConfigRequest( + generative_question_config=generative_question.GenerativeQuestionConfig( + catalog="catalog_value" + ) + ) + ], + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].requests + mock_val = [ + generative_question_service.UpdateGenerativeQuestionConfigRequest( + generative_question_config=generative_question.GenerativeQuestionConfig( + catalog="catalog_value" + ) + ) + ] + assert arg == mock_val + + +def test_batch_update_generative_question_configs_flattened_error(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.batch_update_generative_question_configs( + generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest(), + parent="parent_value", + requests=[ + generative_question_service.UpdateGenerativeQuestionConfigRequest( + generative_question_config=generative_question.GenerativeQuestionConfig( + catalog="catalog_value" + ) + ) + ], + ) + + +@pytest.mark.asyncio +async def test_batch_update_generative_question_configs_flattened_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.batch_update_generative_question_configs), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = ( + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse() + ) + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse() + ) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.batch_update_generative_question_configs( + parent="parent_value", + requests=[ + generative_question_service.UpdateGenerativeQuestionConfigRequest( + generative_question_config=generative_question.GenerativeQuestionConfig( + catalog="catalog_value" + ) + ) + ], + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].requests + mock_val = [ + generative_question_service.UpdateGenerativeQuestionConfigRequest( + generative_question_config=generative_question.GenerativeQuestionConfig( + catalog="catalog_value" + ) + ) + ] + assert arg == mock_val + + +@pytest.mark.asyncio +async def test_batch_update_generative_question_configs_flattened_error_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + await client.batch_update_generative_question_configs( + generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest(), + parent="parent_value", + requests=[ + generative_question_service.UpdateGenerativeQuestionConfigRequest( + generative_question_config=generative_question.GenerativeQuestionConfig( + catalog="catalog_value" + ) + ) + ], + ) + + +@pytest.mark.parametrize( + "request_type", + [ + generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest, + dict, + ], +) +def test_update_generative_questions_feature_config_rest(request_type): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = { + "generative_questions_feature_config": { + "catalog": "projects/sample1/locations/sample2/catalogs/sample3" + } + } + request_init["generative_questions_feature_config"] = { + "catalog": "projects/sample1/locations/sample2/catalogs/sample3", + "feature_enabled": True, + "minimum_products": 1743, + } + # The version of a generated dependency at test runtime may differ from the version used during generation. + # Delete any fields which are not present in the current runtime dependency + # See https://github.com/googleapis/gapic-generator-python/issues/1748 + + # Determine if the message type is proto-plus or protobuf + test_field = generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest.meta.fields[ + "generative_questions_feature_config" + ] + + def get_message_fields(field): + # Given a field which is a message (composite type), return a list with + # all the fields of the message. + # If the field is not a composite type, return an empty list. + message_fields = [] + + if hasattr(field, "message") and field.message: + is_field_type_proto_plus_type = not hasattr(field.message, "DESCRIPTOR") + + if is_field_type_proto_plus_type: + message_fields = field.message.meta.fields.values() + # Add `# pragma: NO COVER` because there may not be any `*_pb2` field types + else: # pragma: NO COVER + message_fields = field.message.DESCRIPTOR.fields + return message_fields + + runtime_nested_fields = [ + (field.name, nested_field.name) + for field in get_message_fields(test_field) + for nested_field in get_message_fields(field) + ] + + subfields_not_in_runtime = [] + + # For each item in the sample request, create a list of sub fields which are not present at runtime + # Add `# pragma: NO COVER` because this test code will not run if all subfields are present at runtime + for field, value in request_init[ + "generative_questions_feature_config" + ].items(): # pragma: NO COVER + result = None + is_repeated = False + # For repeated fields + if isinstance(value, list) and len(value): + is_repeated = True + result = value[0] + # For fields where the type is another message + if isinstance(value, dict): + result = value + + if result and hasattr(result, "keys"): + for subfield in result.keys(): + if (field, subfield) not in runtime_nested_fields: + subfields_not_in_runtime.append( + { + "field": field, + "subfield": subfield, + "is_repeated": is_repeated, + } + ) + + # Remove fields from the sample request which are not present in the runtime version of the dependency + # Add `# pragma: NO COVER` because this test code will not run if all subfields are present at runtime + for subfield_to_delete in subfields_not_in_runtime: # pragma: NO COVER + field = subfield_to_delete.get("field") + field_repeated = subfield_to_delete.get("is_repeated") + subfield = subfield_to_delete.get("subfield") + if subfield: + if field_repeated: + for i in range( + 0, len(request_init["generative_questions_feature_config"][field]) + ): + del request_init["generative_questions_feature_config"][field][i][ + subfield + ] + else: + del request_init["generative_questions_feature_config"][field][subfield] + request = request_type(**request_init) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = generative_question.GenerativeQuestionsFeatureConfig( + catalog="catalog_value", + feature_enabled=True, + minimum_products=1743, + ) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = generative_question.GenerativeQuestionsFeatureConfig.pb( + return_value + ) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + response = client.update_generative_questions_feature_config(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, generative_question.GenerativeQuestionsFeatureConfig) + assert response.catalog == "catalog_value" + assert response.feature_enabled is True + assert response.minimum_products == 1743 + + +def test_update_generative_questions_feature_config_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.update_generative_questions_feature_config + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.update_generative_questions_feature_config + ] = mock_rpc + + request = {} + client.update_generative_questions_feature_config(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.update_generative_questions_feature_config(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_update_generative_questions_feature_config_rest_required_fields( + request_type=generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest, +): + transport_class = transports.GenerativeQuestionServiceRestTransport + + request_init = {} + request = request_type(**request_init) + pb_request = request_type.pb(request) + jsonified_request = json.loads( + json_format.MessageToJson(pb_request, use_integers_for_enums=False) + ) + + # verify fields with default values are dropped + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).update_generative_questions_feature_config._get_unset_required_fields( + jsonified_request + ) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).update_generative_questions_feature_config._get_unset_required_fields( + jsonified_request + ) + # Check that path parameters and body parameters are not mixing in. + assert not set(unset_fields) - set(("update_mask",)) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = generative_question.GenerativeQuestionsFeatureConfig() + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # We need to mock transcode() because providing default values + # for required fields will fail the real version if the http_options + # expect actual values for those fields. + with mock.patch.object(path_template, "transcode") as transcode: + # A uri without fields and an empty body will force all the + # request fields to show up in the query_params. + pb_request = request_type.pb(request) + transcode_result = { + "uri": "v1/sample_method", + "method": "patch", + "query_params": pb_request, + } + transcode_result["body"] = pb_request + transcode.return_value = transcode_result + + response_value = Response() + response_value.status_code = 200 + + # Convert return value to protobuf type + return_value = generative_question.GenerativeQuestionsFeatureConfig.pb( + return_value + ) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + response = client.update_generative_questions_feature_config(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_update_generative_questions_feature_config_rest_unset_required_fields(): + transport = transports.GenerativeQuestionServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = ( + transport.update_generative_questions_feature_config._get_unset_required_fields( + {} + ) + ) + assert set(unset_fields) == ( + set(("updateMask",)) & set(("generativeQuestionsFeatureConfig",)) + ) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_update_generative_questions_feature_config_rest_interceptors(null_interceptor): + transport = transports.GenerativeQuestionServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.GenerativeQuestionServiceRestInterceptor(), + ) + client = GenerativeQuestionServiceClient(transport=transport) + with mock.patch.object( + type(client.transport._session), "request" + ) as req, mock.patch.object( + path_template, "transcode" + ) as transcode, mock.patch.object( + transports.GenerativeQuestionServiceRestInterceptor, + "post_update_generative_questions_feature_config", + ) as post, mock.patch.object( + transports.GenerativeQuestionServiceRestInterceptor, + "pre_update_generative_questions_feature_config", + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest.pb( + generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest() + ) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = Response() + req.return_value.status_code = 200 + req.return_value.request = PreparedRequest() + req.return_value._content = ( + generative_question.GenerativeQuestionsFeatureConfig.to_json( + generative_question.GenerativeQuestionsFeatureConfig() + ) + ) + + request = ( + generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest() + ) + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = generative_question.GenerativeQuestionsFeatureConfig() + + client.update_generative_questions_feature_config( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_update_generative_questions_feature_config_rest_bad_request( + transport: str = "rest", + request_type=generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest, +): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = { + "generative_questions_feature_config": { + "catalog": "projects/sample1/locations/sample2/catalogs/sample3" + } + } + request = request_type(**request_init) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 400 + response_value.request = Request() + req.return_value = response_value + client.update_generative_questions_feature_config(request) + + +def test_update_generative_questions_feature_config_rest_flattened(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = generative_question.GenerativeQuestionsFeatureConfig() + + # get arguments that satisfy an http rule for this method + sample_request = { + "generative_questions_feature_config": { + "catalog": "projects/sample1/locations/sample2/catalogs/sample3" + } + } + + # get truthy value for each flattened field + mock_args = dict( + generative_questions_feature_config=generative_question.GenerativeQuestionsFeatureConfig( + catalog="catalog_value" + ), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + mock_args.update(sample_request) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = generative_question.GenerativeQuestionsFeatureConfig.pb( + return_value + ) + json_return_value = json_format.MessageToJson(return_value) + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + client.update_generative_questions_feature_config(**mock_args) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(req.mock_calls) == 1 + _, args, _ = req.mock_calls[0] + assert path_template.validate( + "%s/v2/{generative_questions_feature_config.catalog=projects/*/locations/*/catalogs/*}/generativeQuestionFeature" + % client.transport._host, + args[1], + ) + + +def test_update_generative_questions_feature_config_rest_flattened_error( + transport: str = "rest", +): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.update_generative_questions_feature_config( + generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest(), + generative_questions_feature_config=generative_question.GenerativeQuestionsFeatureConfig( + catalog="catalog_value" + ), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + +def test_update_generative_questions_feature_config_rest_error(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + +@pytest.mark.parametrize( + "request_type", + [ + generative_question_service.GetGenerativeQuestionsFeatureConfigRequest, + dict, + ], +) +def test_get_generative_questions_feature_config_rest(request_type): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = {"catalog": "projects/sample1/locations/sample2/catalogs/sample3"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = generative_question.GenerativeQuestionsFeatureConfig( + catalog="catalog_value", + feature_enabled=True, + minimum_products=1743, + ) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = generative_question.GenerativeQuestionsFeatureConfig.pb( + return_value + ) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + response = client.get_generative_questions_feature_config(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, generative_question.GenerativeQuestionsFeatureConfig) + assert response.catalog == "catalog_value" + assert response.feature_enabled is True + assert response.minimum_products == 1743 + + +def test_get_generative_questions_feature_config_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.get_generative_questions_feature_config + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.get_generative_questions_feature_config + ] = mock_rpc + + request = {} + client.get_generative_questions_feature_config(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.get_generative_questions_feature_config(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_get_generative_questions_feature_config_rest_required_fields( + request_type=generative_question_service.GetGenerativeQuestionsFeatureConfigRequest, +): + transport_class = transports.GenerativeQuestionServiceRestTransport + + request_init = {} + request_init["catalog"] = "" + request = request_type(**request_init) + pb_request = request_type.pb(request) + jsonified_request = json.loads( + json_format.MessageToJson(pb_request, use_integers_for_enums=False) + ) + + # verify fields with default values are dropped + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).get_generative_questions_feature_config._get_unset_required_fields( + jsonified_request + ) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + jsonified_request["catalog"] = "catalog_value" + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).get_generative_questions_feature_config._get_unset_required_fields( + jsonified_request + ) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + assert "catalog" in jsonified_request + assert jsonified_request["catalog"] == "catalog_value" + + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = generative_question.GenerativeQuestionsFeatureConfig() + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # We need to mock transcode() because providing default values + # for required fields will fail the real version if the http_options + # expect actual values for those fields. + with mock.patch.object(path_template, "transcode") as transcode: + # A uri without fields and an empty body will force all the + # request fields to show up in the query_params. + pb_request = request_type.pb(request) + transcode_result = { + "uri": "v1/sample_method", + "method": "get", + "query_params": pb_request, + } + transcode.return_value = transcode_result + + response_value = Response() + response_value.status_code = 200 + + # Convert return value to protobuf type + return_value = generative_question.GenerativeQuestionsFeatureConfig.pb( + return_value + ) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + response = client.get_generative_questions_feature_config(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_get_generative_questions_feature_config_rest_unset_required_fields(): + transport = transports.GenerativeQuestionServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = ( + transport.get_generative_questions_feature_config._get_unset_required_fields({}) + ) + assert set(unset_fields) == (set(()) & set(("catalog",))) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_get_generative_questions_feature_config_rest_interceptors(null_interceptor): + transport = transports.GenerativeQuestionServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.GenerativeQuestionServiceRestInterceptor(), + ) + client = GenerativeQuestionServiceClient(transport=transport) + with mock.patch.object( + type(client.transport._session), "request" + ) as req, mock.patch.object( + path_template, "transcode" + ) as transcode, mock.patch.object( + transports.GenerativeQuestionServiceRestInterceptor, + "post_get_generative_questions_feature_config", + ) as post, mock.patch.object( + transports.GenerativeQuestionServiceRestInterceptor, + "pre_get_generative_questions_feature_config", + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = ( + generative_question_service.GetGenerativeQuestionsFeatureConfigRequest.pb( + generative_question_service.GetGenerativeQuestionsFeatureConfigRequest() + ) + ) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = Response() + req.return_value.status_code = 200 + req.return_value.request = PreparedRequest() + req.return_value._content = ( + generative_question.GenerativeQuestionsFeatureConfig.to_json( + generative_question.GenerativeQuestionsFeatureConfig() + ) + ) + + request = ( + generative_question_service.GetGenerativeQuestionsFeatureConfigRequest() + ) + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = generative_question.GenerativeQuestionsFeatureConfig() + + client.get_generative_questions_feature_config( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_get_generative_questions_feature_config_rest_bad_request( + transport: str = "rest", + request_type=generative_question_service.GetGenerativeQuestionsFeatureConfigRequest, +): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = {"catalog": "projects/sample1/locations/sample2/catalogs/sample3"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 400 + response_value.request = Request() + req.return_value = response_value + client.get_generative_questions_feature_config(request) + + +def test_get_generative_questions_feature_config_rest_flattened(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = generative_question.GenerativeQuestionsFeatureConfig() + + # get arguments that satisfy an http rule for this method + sample_request = { + "catalog": "projects/sample1/locations/sample2/catalogs/sample3" + } + + # get truthy value for each flattened field + mock_args = dict( + catalog="catalog_value", + ) + mock_args.update(sample_request) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = generative_question.GenerativeQuestionsFeatureConfig.pb( + return_value + ) + json_return_value = json_format.MessageToJson(return_value) + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + client.get_generative_questions_feature_config(**mock_args) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(req.mock_calls) == 1 + _, args, _ = req.mock_calls[0] + assert path_template.validate( + "%s/v2/{catalog=projects/*/locations/*/catalogs/*}/generativeQuestionFeature" + % client.transport._host, + args[1], + ) + + +def test_get_generative_questions_feature_config_rest_flattened_error( + transport: str = "rest", +): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.get_generative_questions_feature_config( + generative_question_service.GetGenerativeQuestionsFeatureConfigRequest(), + catalog="catalog_value", + ) + + +def test_get_generative_questions_feature_config_rest_error(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + +@pytest.mark.parametrize( + "request_type", + [ + generative_question_service.ListGenerativeQuestionConfigsRequest, + dict, + ], +) +def test_list_generative_question_configs_rest(request_type): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = {"parent": "projects/sample1/locations/sample2/catalogs/sample3"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = ( + generative_question_service.ListGenerativeQuestionConfigsResponse() + ) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = ( + generative_question_service.ListGenerativeQuestionConfigsResponse.pb( + return_value + ) + ) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + response = client.list_generative_question_configs(request) + + # Establish that the response is the type that we expect. + assert isinstance( + response, generative_question_service.ListGenerativeQuestionConfigsResponse + ) + + +def test_list_generative_question_configs_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.list_generative_question_configs + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.list_generative_question_configs + ] = mock_rpc + + request = {} + client.list_generative_question_configs(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.list_generative_question_configs(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_list_generative_question_configs_rest_required_fields( + request_type=generative_question_service.ListGenerativeQuestionConfigsRequest, +): + transport_class = transports.GenerativeQuestionServiceRestTransport + + request_init = {} + request_init["parent"] = "" + request = request_type(**request_init) + pb_request = request_type.pb(request) + jsonified_request = json.loads( + json_format.MessageToJson(pb_request, use_integers_for_enums=False) + ) + + # verify fields with default values are dropped + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).list_generative_question_configs._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + jsonified_request["parent"] = "parent_value" + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).list_generative_question_configs._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + assert "parent" in jsonified_request + assert jsonified_request["parent"] == "parent_value" + + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = generative_question_service.ListGenerativeQuestionConfigsResponse() + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # We need to mock transcode() because providing default values + # for required fields will fail the real version if the http_options + # expect actual values for those fields. + with mock.patch.object(path_template, "transcode") as transcode: + # A uri without fields and an empty body will force all the + # request fields to show up in the query_params. + pb_request = request_type.pb(request) + transcode_result = { + "uri": "v1/sample_method", + "method": "get", + "query_params": pb_request, + } + transcode.return_value = transcode_result + + response_value = Response() + response_value.status_code = 200 + + # Convert return value to protobuf type + return_value = ( + generative_question_service.ListGenerativeQuestionConfigsResponse.pb( + return_value + ) + ) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + response = client.list_generative_question_configs(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_list_generative_question_configs_rest_unset_required_fields(): + transport = transports.GenerativeQuestionServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = ( + transport.list_generative_question_configs._get_unset_required_fields({}) + ) + assert set(unset_fields) == (set(()) & set(("parent",))) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_list_generative_question_configs_rest_interceptors(null_interceptor): + transport = transports.GenerativeQuestionServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.GenerativeQuestionServiceRestInterceptor(), + ) + client = GenerativeQuestionServiceClient(transport=transport) + with mock.patch.object( + type(client.transport._session), "request" + ) as req, mock.patch.object( + path_template, "transcode" + ) as transcode, mock.patch.object( + transports.GenerativeQuestionServiceRestInterceptor, + "post_list_generative_question_configs", + ) as post, mock.patch.object( + transports.GenerativeQuestionServiceRestInterceptor, + "pre_list_generative_question_configs", + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = ( + generative_question_service.ListGenerativeQuestionConfigsRequest.pb( + generative_question_service.ListGenerativeQuestionConfigsRequest() + ) + ) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = Response() + req.return_value.status_code = 200 + req.return_value.request = PreparedRequest() + req.return_value._content = ( + generative_question_service.ListGenerativeQuestionConfigsResponse.to_json( + generative_question_service.ListGenerativeQuestionConfigsResponse() + ) + ) + + request = generative_question_service.ListGenerativeQuestionConfigsRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = ( + generative_question_service.ListGenerativeQuestionConfigsResponse() + ) + + client.list_generative_question_configs( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_list_generative_question_configs_rest_bad_request( + transport: str = "rest", + request_type=generative_question_service.ListGenerativeQuestionConfigsRequest, +): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = {"parent": "projects/sample1/locations/sample2/catalogs/sample3"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 400 + response_value.request = Request() + req.return_value = response_value + client.list_generative_question_configs(request) + + +def test_list_generative_question_configs_rest_flattened(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = ( + generative_question_service.ListGenerativeQuestionConfigsResponse() + ) + + # get arguments that satisfy an http rule for this method + sample_request = { + "parent": "projects/sample1/locations/sample2/catalogs/sample3" + } + + # get truthy value for each flattened field + mock_args = dict( + parent="parent_value", + ) + mock_args.update(sample_request) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = ( + generative_question_service.ListGenerativeQuestionConfigsResponse.pb( + return_value + ) + ) + json_return_value = json_format.MessageToJson(return_value) + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + client.list_generative_question_configs(**mock_args) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(req.mock_calls) == 1 + _, args, _ = req.mock_calls[0] + assert path_template.validate( + "%s/v2/{parent=projects/*/locations/*/catalogs/*}/generativeQuestions" + % client.transport._host, + args[1], + ) + + +def test_list_generative_question_configs_rest_flattened_error(transport: str = "rest"): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.list_generative_question_configs( + generative_question_service.ListGenerativeQuestionConfigsRequest(), + parent="parent_value", + ) + + +def test_list_generative_question_configs_rest_error(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + +@pytest.mark.parametrize( + "request_type", + [ + generative_question_service.UpdateGenerativeQuestionConfigRequest, + dict, + ], +) +def test_update_generative_question_config_rest(request_type): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = { + "generative_question_config": { + "catalog": "projects/sample1/locations/sample2/catalogs/sample3" + } + } + request_init["generative_question_config"] = { + "catalog": "projects/sample1/locations/sample2/catalogs/sample3", + "facet": "facet_value", + "generated_question": "generated_question_value", + "final_question": "final_question_value", + "example_values": ["example_values_value1", "example_values_value2"], + "frequency": 0.978, + "allowed_in_conversation": True, + } + # The version of a generated dependency at test runtime may differ from the version used during generation. + # Delete any fields which are not present in the current runtime dependency + # See https://github.com/googleapis/gapic-generator-python/issues/1748 + + # Determine if the message type is proto-plus or protobuf + test_field = ( + generative_question_service.UpdateGenerativeQuestionConfigRequest.meta.fields[ + "generative_question_config" + ] + ) + + def get_message_fields(field): + # Given a field which is a message (composite type), return a list with + # all the fields of the message. + # If the field is not a composite type, return an empty list. + message_fields = [] + + if hasattr(field, "message") and field.message: + is_field_type_proto_plus_type = not hasattr(field.message, "DESCRIPTOR") + + if is_field_type_proto_plus_type: + message_fields = field.message.meta.fields.values() + # Add `# pragma: NO COVER` because there may not be any `*_pb2` field types + else: # pragma: NO COVER + message_fields = field.message.DESCRIPTOR.fields + return message_fields + + runtime_nested_fields = [ + (field.name, nested_field.name) + for field in get_message_fields(test_field) + for nested_field in get_message_fields(field) + ] + + subfields_not_in_runtime = [] + + # For each item in the sample request, create a list of sub fields which are not present at runtime + # Add `# pragma: NO COVER` because this test code will not run if all subfields are present at runtime + for field, value in request_init[ + "generative_question_config" + ].items(): # pragma: NO COVER + result = None + is_repeated = False + # For repeated fields + if isinstance(value, list) and len(value): + is_repeated = True + result = value[0] + # For fields where the type is another message + if isinstance(value, dict): + result = value + + if result and hasattr(result, "keys"): + for subfield in result.keys(): + if (field, subfield) not in runtime_nested_fields: + subfields_not_in_runtime.append( + { + "field": field, + "subfield": subfield, + "is_repeated": is_repeated, + } + ) + + # Remove fields from the sample request which are not present in the runtime version of the dependency + # Add `# pragma: NO COVER` because this test code will not run if all subfields are present at runtime + for subfield_to_delete in subfields_not_in_runtime: # pragma: NO COVER + field = subfield_to_delete.get("field") + field_repeated = subfield_to_delete.get("is_repeated") + subfield = subfield_to_delete.get("subfield") + if subfield: + if field_repeated: + for i in range( + 0, len(request_init["generative_question_config"][field]) + ): + del request_init["generative_question_config"][field][i][subfield] + else: + del request_init["generative_question_config"][field][subfield] + request = request_type(**request_init) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = generative_question.GenerativeQuestionConfig( + catalog="catalog_value", + facet="facet_value", + generated_question="generated_question_value", + final_question="final_question_value", + example_values=["example_values_value"], + frequency=0.978, + allowed_in_conversation=True, + ) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = generative_question.GenerativeQuestionConfig.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + response = client.update_generative_question_config(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, generative_question.GenerativeQuestionConfig) + assert response.catalog == "catalog_value" + assert response.facet == "facet_value" + assert response.generated_question == "generated_question_value" + assert response.final_question == "final_question_value" + assert response.example_values == ["example_values_value"] + assert math.isclose(response.frequency, 0.978, rel_tol=1e-6) + assert response.allowed_in_conversation is True + + +def test_update_generative_question_config_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.update_generative_question_config + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.update_generative_question_config + ] = mock_rpc + + request = {} + client.update_generative_question_config(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.update_generative_question_config(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_update_generative_question_config_rest_required_fields( + request_type=generative_question_service.UpdateGenerativeQuestionConfigRequest, +): + transport_class = transports.GenerativeQuestionServiceRestTransport + + request_init = {} + request = request_type(**request_init) + pb_request = request_type.pb(request) + jsonified_request = json.loads( + json_format.MessageToJson(pb_request, use_integers_for_enums=False) + ) + + # verify fields with default values are dropped + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).update_generative_question_config._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).update_generative_question_config._get_unset_required_fields(jsonified_request) + # Check that path parameters and body parameters are not mixing in. + assert not set(unset_fields) - set(("update_mask",)) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = generative_question.GenerativeQuestionConfig() + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # We need to mock transcode() because providing default values + # for required fields will fail the real version if the http_options + # expect actual values for those fields. + with mock.patch.object(path_template, "transcode") as transcode: + # A uri without fields and an empty body will force all the + # request fields to show up in the query_params. + pb_request = request_type.pb(request) + transcode_result = { + "uri": "v1/sample_method", + "method": "patch", + "query_params": pb_request, + } + transcode_result["body"] = pb_request + transcode.return_value = transcode_result + + response_value = Response() + response_value.status_code = 200 + + # Convert return value to protobuf type + return_value = generative_question.GenerativeQuestionConfig.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + response = client.update_generative_question_config(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_update_generative_question_config_rest_unset_required_fields(): + transport = transports.GenerativeQuestionServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = ( + transport.update_generative_question_config._get_unset_required_fields({}) + ) + assert set(unset_fields) == ( + set(("updateMask",)) & set(("generativeQuestionConfig",)) + ) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_update_generative_question_config_rest_interceptors(null_interceptor): + transport = transports.GenerativeQuestionServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.GenerativeQuestionServiceRestInterceptor(), + ) + client = GenerativeQuestionServiceClient(transport=transport) + with mock.patch.object( + type(client.transport._session), "request" + ) as req, mock.patch.object( + path_template, "transcode" + ) as transcode, mock.patch.object( + transports.GenerativeQuestionServiceRestInterceptor, + "post_update_generative_question_config", + ) as post, mock.patch.object( + transports.GenerativeQuestionServiceRestInterceptor, + "pre_update_generative_question_config", + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = ( + generative_question_service.UpdateGenerativeQuestionConfigRequest.pb( + generative_question_service.UpdateGenerativeQuestionConfigRequest() + ) + ) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = Response() + req.return_value.status_code = 200 + req.return_value.request = PreparedRequest() + req.return_value._content = ( + generative_question.GenerativeQuestionConfig.to_json( + generative_question.GenerativeQuestionConfig() + ) + ) + + request = generative_question_service.UpdateGenerativeQuestionConfigRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = generative_question.GenerativeQuestionConfig() + + client.update_generative_question_config( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_update_generative_question_config_rest_bad_request( + transport: str = "rest", + request_type=generative_question_service.UpdateGenerativeQuestionConfigRequest, +): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = { + "generative_question_config": { + "catalog": "projects/sample1/locations/sample2/catalogs/sample3" + } + } + request = request_type(**request_init) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 400 + response_value.request = Request() + req.return_value = response_value + client.update_generative_question_config(request) + + +def test_update_generative_question_config_rest_flattened(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = generative_question.GenerativeQuestionConfig() + + # get arguments that satisfy an http rule for this method + sample_request = { + "generative_question_config": { + "catalog": "projects/sample1/locations/sample2/catalogs/sample3" + } + } + + # get truthy value for each flattened field + mock_args = dict( + generative_question_config=generative_question.GenerativeQuestionConfig( + catalog="catalog_value" + ), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + mock_args.update(sample_request) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = generative_question.GenerativeQuestionConfig.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + client.update_generative_question_config(**mock_args) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(req.mock_calls) == 1 + _, args, _ = req.mock_calls[0] + assert path_template.validate( + "%s/v2/{generative_question_config.catalog=projects/*/locations/*/catalogs/*}/generativeQuestion" + % client.transport._host, + args[1], + ) + + +def test_update_generative_question_config_rest_flattened_error( + transport: str = "rest", +): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.update_generative_question_config( + generative_question_service.UpdateGenerativeQuestionConfigRequest(), + generative_question_config=generative_question.GenerativeQuestionConfig( + catalog="catalog_value" + ), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + +def test_update_generative_question_config_rest_error(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + +@pytest.mark.parametrize( + "request_type", + [ + generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest, + dict, + ], +) +def test_batch_update_generative_question_configs_rest(request_type): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = {"parent": "projects/sample1/locations/sample2/catalogs/sample3"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = ( + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse() + ) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = ( + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse.pb( + return_value + ) + ) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + response = client.batch_update_generative_question_configs(request) + + # Establish that the response is the type that we expect. + assert isinstance( + response, + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse, + ) + + +def test_batch_update_generative_question_configs_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.batch_update_generative_question_configs + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.batch_update_generative_question_configs + ] = mock_rpc + + request = {} + client.batch_update_generative_question_configs(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.batch_update_generative_question_configs(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_batch_update_generative_question_configs_rest_required_fields( + request_type=generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest, +): + transport_class = transports.GenerativeQuestionServiceRestTransport + + request_init = {} + request = request_type(**request_init) + pb_request = request_type.pb(request) + jsonified_request = json.loads( + json_format.MessageToJson(pb_request, use_integers_for_enums=False) + ) + + # verify fields with default values are dropped + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).batch_update_generative_question_configs._get_unset_required_fields( + jsonified_request + ) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).batch_update_generative_question_configs._get_unset_required_fields( + jsonified_request + ) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = ( + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse() + ) + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # We need to mock transcode() because providing default values + # for required fields will fail the real version if the http_options + # expect actual values for those fields. + with mock.patch.object(path_template, "transcode") as transcode: + # A uri without fields and an empty body will force all the + # request fields to show up in the query_params. + pb_request = request_type.pb(request) + transcode_result = { + "uri": "v1/sample_method", + "method": "post", + "query_params": pb_request, + } + transcode_result["body"] = pb_request + transcode.return_value = transcode_result + + response_value = Response() + response_value.status_code = 200 + + # Convert return value to protobuf type + return_value = generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse.pb( + return_value + ) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + response = client.batch_update_generative_question_configs(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_batch_update_generative_question_configs_rest_unset_required_fields(): + transport = transports.GenerativeQuestionServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = ( + transport.batch_update_generative_question_configs._get_unset_required_fields( + {} + ) + ) + assert set(unset_fields) == (set(()) & set(("requests",))) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_batch_update_generative_question_configs_rest_interceptors(null_interceptor): + transport = transports.GenerativeQuestionServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.GenerativeQuestionServiceRestInterceptor(), + ) + client = GenerativeQuestionServiceClient(transport=transport) + with mock.patch.object( + type(client.transport._session), "request" + ) as req, mock.patch.object( + path_template, "transcode" + ) as transcode, mock.patch.object( + transports.GenerativeQuestionServiceRestInterceptor, + "post_batch_update_generative_question_configs", + ) as post, mock.patch.object( + transports.GenerativeQuestionServiceRestInterceptor, + "pre_batch_update_generative_question_configs", + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest.pb( + generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest() + ) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = Response() + req.return_value.status_code = 200 + req.return_value.request = PreparedRequest() + req.return_value._content = generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse.to_json( + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse() + ) + + request = ( + generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest() + ) + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = ( + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse() + ) + + client.batch_update_generative_question_configs( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_batch_update_generative_question_configs_rest_bad_request( + transport: str = "rest", + request_type=generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest, +): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = {"parent": "projects/sample1/locations/sample2/catalogs/sample3"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 400 + response_value.request = Request() + req.return_value = response_value + client.batch_update_generative_question_configs(request) + + +def test_batch_update_generative_question_configs_rest_flattened(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = ( + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse() + ) + + # get arguments that satisfy an http rule for this method + sample_request = { + "parent": "projects/sample1/locations/sample2/catalogs/sample3" + } + + # get truthy value for each flattened field + mock_args = dict( + parent="parent_value", + requests=[ + generative_question_service.UpdateGenerativeQuestionConfigRequest( + generative_question_config=generative_question.GenerativeQuestionConfig( + catalog="catalog_value" + ) + ) + ], + ) + mock_args.update(sample_request) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = ( + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse.pb( + return_value + ) + ) + json_return_value = json_format.MessageToJson(return_value) + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + client.batch_update_generative_question_configs(**mock_args) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(req.mock_calls) == 1 + _, args, _ = req.mock_calls[0] + assert path_template.validate( + "%s/v2/{parent=projects/*/locations/*/catalogs/*}/generativeQuestion:batchUpdate" + % client.transport._host, + args[1], + ) + + +def test_batch_update_generative_question_configs_rest_flattened_error( + transport: str = "rest", +): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.batch_update_generative_question_configs( + generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest(), + parent="parent_value", + requests=[ + generative_question_service.UpdateGenerativeQuestionConfigRequest( + generative_question_config=generative_question.GenerativeQuestionConfig( + catalog="catalog_value" + ) + ) + ], + ) + + +def test_batch_update_generative_question_configs_rest_error(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + +def test_credentials_transport_error(): + # It is an error to provide credentials and a transport instance. + transport = transports.GenerativeQuestionServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + with pytest.raises(ValueError): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # It is an error to provide a credentials file and a transport instance. + transport = transports.GenerativeQuestionServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + with pytest.raises(ValueError): + client = GenerativeQuestionServiceClient( + client_options={"credentials_file": "credentials.json"}, + transport=transport, + ) + + # It is an error to provide an api_key and a transport instance. + transport = transports.GenerativeQuestionServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + options = client_options.ClientOptions() + options.api_key = "api_key" + with pytest.raises(ValueError): + client = GenerativeQuestionServiceClient( + client_options=options, + transport=transport, + ) + + # It is an error to provide an api_key and a credential. + options = client_options.ClientOptions() + options.api_key = "api_key" + with pytest.raises(ValueError): + client = GenerativeQuestionServiceClient( + client_options=options, credentials=ga_credentials.AnonymousCredentials() + ) + + # It is an error to provide scopes and a transport instance. + transport = transports.GenerativeQuestionServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + with pytest.raises(ValueError): + client = GenerativeQuestionServiceClient( + client_options={"scopes": ["1", "2"]}, + transport=transport, + ) + + +def test_transport_instance(): + # A client may be instantiated with a custom transport instance. + transport = transports.GenerativeQuestionServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + client = GenerativeQuestionServiceClient(transport=transport) + assert client.transport is transport + + +def test_transport_get_channel(): + # A client may be instantiated with a custom transport instance. + transport = transports.GenerativeQuestionServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + channel = transport.grpc_channel + assert channel + + transport = transports.GenerativeQuestionServiceGrpcAsyncIOTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + channel = transport.grpc_channel + assert channel + + +@pytest.mark.parametrize( + "transport_class", + [ + transports.GenerativeQuestionServiceGrpcTransport, + transports.GenerativeQuestionServiceGrpcAsyncIOTransport, + transports.GenerativeQuestionServiceRestTransport, + ], +) +def test_transport_adc(transport_class): + # Test default credentials are used if not provided. + with mock.patch.object(google.auth, "default") as adc: + adc.return_value = (ga_credentials.AnonymousCredentials(), None) + transport_class() + adc.assert_called_once() + + +@pytest.mark.parametrize( + "transport_name", + [ + "grpc", + "rest", + ], +) +def test_transport_kind(transport_name): + transport = GenerativeQuestionServiceClient.get_transport_class(transport_name)( + credentials=ga_credentials.AnonymousCredentials(), + ) + assert transport.kind == transport_name + + +def test_transport_grpc_default(): + # A client should use the gRPC transport by default. + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + assert isinstance( + client.transport, + transports.GenerativeQuestionServiceGrpcTransport, + ) + + +def test_generative_question_service_base_transport_error(): + # Passing both a credentials object and credentials_file should raise an error + with pytest.raises(core_exceptions.DuplicateCredentialArgs): + transport = transports.GenerativeQuestionServiceTransport( + credentials=ga_credentials.AnonymousCredentials(), + credentials_file="credentials.json", + ) + + +def test_generative_question_service_base_transport(): + # Instantiate the base transport. + with mock.patch( + "google.cloud.retail_v2.services.generative_question_service.transports.GenerativeQuestionServiceTransport.__init__" + ) as Transport: + Transport.return_value = None + transport = transports.GenerativeQuestionServiceTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Every method on the transport should just blindly + # raise NotImplementedError. + methods = ( + "update_generative_questions_feature_config", + "get_generative_questions_feature_config", + "list_generative_question_configs", + "update_generative_question_config", + "batch_update_generative_question_configs", + "get_operation", + "list_operations", + ) + for method in methods: + with pytest.raises(NotImplementedError): + getattr(transport, method)(request=object()) + + with pytest.raises(NotImplementedError): + transport.close() + + # Catch all for all remaining methods and properties + remainder = [ + "kind", + ] + for r in remainder: + with pytest.raises(NotImplementedError): + getattr(transport, r)() + + +def test_generative_question_service_base_transport_with_credentials_file(): + # Instantiate the base transport with a credentials file + with mock.patch.object( + google.auth, "load_credentials_from_file", autospec=True + ) as load_creds, mock.patch( + "google.cloud.retail_v2.services.generative_question_service.transports.GenerativeQuestionServiceTransport._prep_wrapped_messages" + ) as Transport: + Transport.return_value = None + load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) + transport = transports.GenerativeQuestionServiceTransport( + credentials_file="credentials.json", + quota_project_id="octopus", + ) + load_creds.assert_called_once_with( + "credentials.json", + scopes=None, + default_scopes=("https://www.googleapis.com/auth/cloud-platform",), + quota_project_id="octopus", + ) + + +def test_generative_question_service_base_transport_with_adc(): + # Test the default credentials are used if credentials and credentials_file are None. + with mock.patch.object(google.auth, "default", autospec=True) as adc, mock.patch( + "google.cloud.retail_v2.services.generative_question_service.transports.GenerativeQuestionServiceTransport._prep_wrapped_messages" + ) as Transport: + Transport.return_value = None + adc.return_value = (ga_credentials.AnonymousCredentials(), None) + transport = transports.GenerativeQuestionServiceTransport() + adc.assert_called_once() + + +def test_generative_question_service_auth_adc(): + # If no credentials are provided, we should use ADC credentials. + with mock.patch.object(google.auth, "default", autospec=True) as adc: + adc.return_value = (ga_credentials.AnonymousCredentials(), None) + GenerativeQuestionServiceClient() + adc.assert_called_once_with( + scopes=None, + default_scopes=("https://www.googleapis.com/auth/cloud-platform",), + quota_project_id=None, + ) + + +@pytest.mark.parametrize( + "transport_class", + [ + transports.GenerativeQuestionServiceGrpcTransport, + transports.GenerativeQuestionServiceGrpcAsyncIOTransport, + ], +) +def test_generative_question_service_transport_auth_adc(transport_class): + # If credentials and host are not provided, the transport class should use + # ADC credentials. + with mock.patch.object(google.auth, "default", autospec=True) as adc: + adc.return_value = (ga_credentials.AnonymousCredentials(), None) + transport_class(quota_project_id="octopus", scopes=["1", "2"]) + adc.assert_called_once_with( + scopes=["1", "2"], + default_scopes=("https://www.googleapis.com/auth/cloud-platform",), + quota_project_id="octopus", + ) + + +@pytest.mark.parametrize( + "transport_class", + [ + transports.GenerativeQuestionServiceGrpcTransport, + transports.GenerativeQuestionServiceGrpcAsyncIOTransport, + transports.GenerativeQuestionServiceRestTransport, + ], +) +def test_generative_question_service_transport_auth_gdch_credentials(transport_class): + host = "https://language.com" + api_audience_tests = [None, "https://language2.com"] + api_audience_expect = [host, "https://language2.com"] + for t, e in zip(api_audience_tests, api_audience_expect): + with mock.patch.object(google.auth, "default", autospec=True) as adc: + gdch_mock = mock.MagicMock() + type(gdch_mock).with_gdch_audience = mock.PropertyMock( + return_value=gdch_mock + ) + adc.return_value = (gdch_mock, None) + transport_class(host=host, api_audience=t) + gdch_mock.with_gdch_audience.assert_called_once_with(e) + + +@pytest.mark.parametrize( + "transport_class,grpc_helpers", + [ + (transports.GenerativeQuestionServiceGrpcTransport, grpc_helpers), + (transports.GenerativeQuestionServiceGrpcAsyncIOTransport, grpc_helpers_async), + ], +) +def test_generative_question_service_transport_create_channel( + transport_class, grpc_helpers +): + # If credentials and host are not provided, the transport class should use + # ADC credentials. + with mock.patch.object( + google.auth, "default", autospec=True + ) as adc, mock.patch.object( + grpc_helpers, "create_channel", autospec=True + ) as create_channel: + creds = ga_credentials.AnonymousCredentials() + adc.return_value = (creds, None) + transport_class(quota_project_id="octopus", scopes=["1", "2"]) + + create_channel.assert_called_with( + "retail.googleapis.com:443", + credentials=creds, + credentials_file=None, + quota_project_id="octopus", + default_scopes=("https://www.googleapis.com/auth/cloud-platform",), + scopes=["1", "2"], + default_host="retail.googleapis.com", + ssl_credentials=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + +@pytest.mark.parametrize( + "transport_class", + [ + transports.GenerativeQuestionServiceGrpcTransport, + transports.GenerativeQuestionServiceGrpcAsyncIOTransport, + ], +) +def test_generative_question_service_grpc_transport_client_cert_source_for_mtls( + transport_class, +): + cred = ga_credentials.AnonymousCredentials() + + # Check ssl_channel_credentials is used if provided. + with mock.patch.object(transport_class, "create_channel") as mock_create_channel: + mock_ssl_channel_creds = mock.Mock() + transport_class( + host="squid.clam.whelk", + credentials=cred, + ssl_channel_credentials=mock_ssl_channel_creds, + ) + mock_create_channel.assert_called_once_with( + "squid.clam.whelk:443", + credentials=cred, + credentials_file=None, + scopes=None, + ssl_credentials=mock_ssl_channel_creds, + quota_project_id=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Check if ssl_channel_credentials is not provided, then client_cert_source_for_mtls + # is used. + with mock.patch.object(transport_class, "create_channel", return_value=mock.Mock()): + with mock.patch("grpc.ssl_channel_credentials") as mock_ssl_cred: + transport_class( + credentials=cred, + client_cert_source_for_mtls=client_cert_source_callback, + ) + expected_cert, expected_key = client_cert_source_callback() + mock_ssl_cred.assert_called_once_with( + certificate_chain=expected_cert, private_key=expected_key + ) + + +def test_generative_question_service_http_transport_client_cert_source_for_mtls(): + cred = ga_credentials.AnonymousCredentials() + with mock.patch( + "google.auth.transport.requests.AuthorizedSession.configure_mtls_channel" + ) as mock_configure_mtls_channel: + transports.GenerativeQuestionServiceRestTransport( + credentials=cred, client_cert_source_for_mtls=client_cert_source_callback + ) + mock_configure_mtls_channel.assert_called_once_with(client_cert_source_callback) + + +@pytest.mark.parametrize( + "transport_name", + [ + "grpc", + "grpc_asyncio", + "rest", + ], +) +def test_generative_question_service_host_no_port(transport_name): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + client_options=client_options.ClientOptions( + api_endpoint="retail.googleapis.com" + ), + transport=transport_name, + ) + assert client.transport._host == ( + "retail.googleapis.com:443" + if transport_name in ["grpc", "grpc_asyncio"] + else "https://retail.googleapis.com" + ) + + +@pytest.mark.parametrize( + "transport_name", + [ + "grpc", + "grpc_asyncio", + "rest", + ], +) +def test_generative_question_service_host_with_port(transport_name): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + client_options=client_options.ClientOptions( + api_endpoint="retail.googleapis.com:8000" + ), + transport=transport_name, + ) + assert client.transport._host == ( + "retail.googleapis.com:8000" + if transport_name in ["grpc", "grpc_asyncio"] + else "https://retail.googleapis.com:8000" + ) + + +@pytest.mark.parametrize( + "transport_name", + [ + "rest", + ], +) +def test_generative_question_service_client_transport_session_collision(transport_name): + creds1 = ga_credentials.AnonymousCredentials() + creds2 = ga_credentials.AnonymousCredentials() + client1 = GenerativeQuestionServiceClient( + credentials=creds1, + transport=transport_name, + ) + client2 = GenerativeQuestionServiceClient( + credentials=creds2, + transport=transport_name, + ) + session1 = client1.transport.update_generative_questions_feature_config._session + session2 = client2.transport.update_generative_questions_feature_config._session + assert session1 != session2 + session1 = client1.transport.get_generative_questions_feature_config._session + session2 = client2.transport.get_generative_questions_feature_config._session + assert session1 != session2 + session1 = client1.transport.list_generative_question_configs._session + session2 = client2.transport.list_generative_question_configs._session + assert session1 != session2 + session1 = client1.transport.update_generative_question_config._session + session2 = client2.transport.update_generative_question_config._session + assert session1 != session2 + session1 = client1.transport.batch_update_generative_question_configs._session + session2 = client2.transport.batch_update_generative_question_configs._session + assert session1 != session2 + + +def test_generative_question_service_grpc_transport_channel(): + channel = grpc.secure_channel("http://localhost/", grpc.local_channel_credentials()) + + # Check that channel is used if provided. + transport = transports.GenerativeQuestionServiceGrpcTransport( + host="squid.clam.whelk", + channel=channel, + ) + assert transport.grpc_channel == channel + assert transport._host == "squid.clam.whelk:443" + assert transport._ssl_channel_credentials == None + + +def test_generative_question_service_grpc_asyncio_transport_channel(): + channel = aio.secure_channel("http://localhost/", grpc.local_channel_credentials()) + + # Check that channel is used if provided. + transport = transports.GenerativeQuestionServiceGrpcAsyncIOTransport( + host="squid.clam.whelk", + channel=channel, + ) + assert transport.grpc_channel == channel + assert transport._host == "squid.clam.whelk:443" + assert transport._ssl_channel_credentials == None + + +# Remove this test when deprecated arguments (api_mtls_endpoint, client_cert_source) are +# removed from grpc/grpc_asyncio transport constructor. +@pytest.mark.parametrize( + "transport_class", + [ + transports.GenerativeQuestionServiceGrpcTransport, + transports.GenerativeQuestionServiceGrpcAsyncIOTransport, + ], +) +def test_generative_question_service_transport_channel_mtls_with_client_cert_source( + transport_class, +): + with mock.patch( + "grpc.ssl_channel_credentials", autospec=True + ) as grpc_ssl_channel_cred: + with mock.patch.object( + transport_class, "create_channel" + ) as grpc_create_channel: + mock_ssl_cred = mock.Mock() + grpc_ssl_channel_cred.return_value = mock_ssl_cred + + mock_grpc_channel = mock.Mock() + grpc_create_channel.return_value = mock_grpc_channel + + cred = ga_credentials.AnonymousCredentials() + with pytest.warns(DeprecationWarning): + with mock.patch.object(google.auth, "default") as adc: + adc.return_value = (cred, None) + transport = transport_class( + host="squid.clam.whelk", + api_mtls_endpoint="mtls.squid.clam.whelk", + client_cert_source=client_cert_source_callback, + ) + adc.assert_called_once() + + grpc_ssl_channel_cred.assert_called_once_with( + certificate_chain=b"cert bytes", private_key=b"key bytes" + ) + grpc_create_channel.assert_called_once_with( + "mtls.squid.clam.whelk:443", + credentials=cred, + credentials_file=None, + scopes=None, + ssl_credentials=mock_ssl_cred, + quota_project_id=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + assert transport.grpc_channel == mock_grpc_channel + assert transport._ssl_channel_credentials == mock_ssl_cred + + +# Remove this test when deprecated arguments (api_mtls_endpoint, client_cert_source) are +# removed from grpc/grpc_asyncio transport constructor. +@pytest.mark.parametrize( + "transport_class", + [ + transports.GenerativeQuestionServiceGrpcTransport, + transports.GenerativeQuestionServiceGrpcAsyncIOTransport, + ], +) +def test_generative_question_service_transport_channel_mtls_with_adc(transport_class): + mock_ssl_cred = mock.Mock() + with mock.patch.multiple( + "google.auth.transport.grpc.SslCredentials", + __init__=mock.Mock(return_value=None), + ssl_credentials=mock.PropertyMock(return_value=mock_ssl_cred), + ): + with mock.patch.object( + transport_class, "create_channel" + ) as grpc_create_channel: + mock_grpc_channel = mock.Mock() + grpc_create_channel.return_value = mock_grpc_channel + mock_cred = mock.Mock() + + with pytest.warns(DeprecationWarning): + transport = transport_class( + host="squid.clam.whelk", + credentials=mock_cred, + api_mtls_endpoint="mtls.squid.clam.whelk", + client_cert_source=None, + ) + + grpc_create_channel.assert_called_once_with( + "mtls.squid.clam.whelk:443", + credentials=mock_cred, + credentials_file=None, + scopes=None, + ssl_credentials=mock_ssl_cred, + quota_project_id=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + assert transport.grpc_channel == mock_grpc_channel + + +def test_catalog_path(): + project = "squid" + location = "clam" + catalog = "whelk" + expected = "projects/{project}/locations/{location}/catalogs/{catalog}".format( + project=project, + location=location, + catalog=catalog, + ) + actual = GenerativeQuestionServiceClient.catalog_path(project, location, catalog) + assert expected == actual + + +def test_parse_catalog_path(): + expected = { + "project": "octopus", + "location": "oyster", + "catalog": "nudibranch", + } + path = GenerativeQuestionServiceClient.catalog_path(**expected) + + # Check that the path construction is reversible. + actual = GenerativeQuestionServiceClient.parse_catalog_path(path) + assert expected == actual + + +def test_common_billing_account_path(): + billing_account = "cuttlefish" + expected = "billingAccounts/{billing_account}".format( + billing_account=billing_account, + ) + actual = GenerativeQuestionServiceClient.common_billing_account_path( + billing_account + ) + assert expected == actual + + +def test_parse_common_billing_account_path(): + expected = { + "billing_account": "mussel", + } + path = GenerativeQuestionServiceClient.common_billing_account_path(**expected) + + # Check that the path construction is reversible. + actual = GenerativeQuestionServiceClient.parse_common_billing_account_path(path) + assert expected == actual + + +def test_common_folder_path(): + folder = "winkle" + expected = "folders/{folder}".format( + folder=folder, + ) + actual = GenerativeQuestionServiceClient.common_folder_path(folder) + assert expected == actual + + +def test_parse_common_folder_path(): + expected = { + "folder": "nautilus", + } + path = GenerativeQuestionServiceClient.common_folder_path(**expected) + + # Check that the path construction is reversible. + actual = GenerativeQuestionServiceClient.parse_common_folder_path(path) + assert expected == actual + + +def test_common_organization_path(): + organization = "scallop" + expected = "organizations/{organization}".format( + organization=organization, + ) + actual = GenerativeQuestionServiceClient.common_organization_path(organization) + assert expected == actual + + +def test_parse_common_organization_path(): + expected = { + "organization": "abalone", + } + path = GenerativeQuestionServiceClient.common_organization_path(**expected) + + # Check that the path construction is reversible. + actual = GenerativeQuestionServiceClient.parse_common_organization_path(path) + assert expected == actual + + +def test_common_project_path(): + project = "squid" + expected = "projects/{project}".format( + project=project, + ) + actual = GenerativeQuestionServiceClient.common_project_path(project) + assert expected == actual + + +def test_parse_common_project_path(): + expected = { + "project": "clam", + } + path = GenerativeQuestionServiceClient.common_project_path(**expected) + + # Check that the path construction is reversible. + actual = GenerativeQuestionServiceClient.parse_common_project_path(path) + assert expected == actual + + +def test_common_location_path(): + project = "whelk" + location = "octopus" + expected = "projects/{project}/locations/{location}".format( + project=project, + location=location, + ) + actual = GenerativeQuestionServiceClient.common_location_path(project, location) + assert expected == actual + + +def test_parse_common_location_path(): + expected = { + "project": "oyster", + "location": "nudibranch", + } + path = GenerativeQuestionServiceClient.common_location_path(**expected) + + # Check that the path construction is reversible. + actual = GenerativeQuestionServiceClient.parse_common_location_path(path) + assert expected == actual + + +def test_client_with_default_client_info(): + client_info = gapic_v1.client_info.ClientInfo() + + with mock.patch.object( + transports.GenerativeQuestionServiceTransport, "_prep_wrapped_messages" + ) as prep: + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + client_info=client_info, + ) + prep.assert_called_once_with(client_info) + + with mock.patch.object( + transports.GenerativeQuestionServiceTransport, "_prep_wrapped_messages" + ) as prep: + transport_class = GenerativeQuestionServiceClient.get_transport_class() + transport = transport_class( + credentials=ga_credentials.AnonymousCredentials(), + client_info=client_info, + ) + prep.assert_called_once_with(client_info) + + +@pytest.mark.asyncio +async def test_transport_close_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + with mock.patch.object( + type(getattr(client.transport, "grpc_channel")), "close" + ) as close: + async with client: + close.assert_not_called() + close.assert_called_once() + + +def test_get_operation_rest_bad_request( + transport: str = "rest", request_type=operations_pb2.GetOperationRequest +): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + request = request_type() + request = json_format.ParseDict( + {"name": "projects/sample1/locations/sample2/operations/sample3"}, request + ) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 400 + response_value.request = Request() + req.return_value = response_value + client.get_operation(request) + + +@pytest.mark.parametrize( + "request_type", + [ + operations_pb2.GetOperationRequest, + dict, + ], +) +def test_get_operation_rest(request_type): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request_init = {"name": "projects/sample1/locations/sample2/operations/sample3"} + request = request_type(**request_init) + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = operations_pb2.Operation() + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + response = client.get_operation(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, operations_pb2.Operation) + + +def test_list_operations_rest_bad_request( + transport: str = "rest", request_type=operations_pb2.ListOperationsRequest +): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + request = request_type() + request = json_format.ParseDict( + {"name": "projects/sample1/locations/sample2"}, request + ) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 400 + response_value.request = Request() + req.return_value = response_value + client.list_operations(request) + + +@pytest.mark.parametrize( + "request_type", + [ + operations_pb2.ListOperationsRequest, + dict, + ], +) +def test_list_operations_rest(request_type): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request_init = {"name": "projects/sample1/locations/sample2"} + request = request_type(**request_init) + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = operations_pb2.ListOperationsResponse() + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + response = client.list_operations(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, operations_pb2.ListOperationsResponse) + + +def test_get_operation(transport: str = "grpc"): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = operations_pb2.GetOperationRequest() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_operation), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.Operation() + response = client.get_operation(request) + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, operations_pb2.Operation) + + +@pytest.mark.asyncio +async def test_get_operation_async(transport: str = "grpc_asyncio"): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = operations_pb2.GetOperationRequest() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_operation), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation() + ) + response = await client.get_operation(request) + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, operations_pb2.Operation) + + +def test_get_operation_field_headers(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = operations_pb2.GetOperationRequest() + request.name = "locations" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_operation), "__call__") as call: + call.return_value = operations_pb2.Operation() + + client.get_operation(request) + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "name=locations", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_get_operation_field_headers_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = operations_pb2.GetOperationRequest() + request.name = "locations" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_operation), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation() + ) + await client.get_operation(request) + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "name=locations", + ) in kw["metadata"] + + +def test_get_operation_from_dict(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_operation), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.Operation() + + response = client.get_operation( + request={ + "name": "locations", + } + ) + call.assert_called() + + +@pytest.mark.asyncio +async def test_get_operation_from_dict_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_operation), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation() + ) + response = await client.get_operation( + request={ + "name": "locations", + } + ) + call.assert_called() + + +def test_list_operations(transport: str = "grpc"): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = operations_pb2.ListOperationsRequest() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_operations), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.ListOperationsResponse() + response = client.list_operations(request) + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, operations_pb2.ListOperationsResponse) + + +@pytest.mark.asyncio +async def test_list_operations_async(transport: str = "grpc_asyncio"): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = operations_pb2.ListOperationsRequest() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_operations), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.ListOperationsResponse() + ) + response = await client.list_operations(request) + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, operations_pb2.ListOperationsResponse) + + +def test_list_operations_field_headers(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = operations_pb2.ListOperationsRequest() + request.name = "locations" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_operations), "__call__") as call: + call.return_value = operations_pb2.ListOperationsResponse() + + client.list_operations(request) + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "name=locations", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_list_operations_field_headers_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = operations_pb2.ListOperationsRequest() + request.name = "locations" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_operations), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.ListOperationsResponse() + ) + await client.list_operations(request) + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "name=locations", + ) in kw["metadata"] + + +def test_list_operations_from_dict(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_operations), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.ListOperationsResponse() + + response = client.list_operations( + request={ + "name": "locations", + } + ) + call.assert_called() + + +@pytest.mark.asyncio +async def test_list_operations_from_dict_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_operations), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.ListOperationsResponse() + ) + response = await client.list_operations( + request={ + "name": "locations", + } + ) + call.assert_called() + + +def test_transport_close(): + transports = { + "rest": "_session", + "grpc": "_grpc_channel", + } + + for transport, close_name in transports.items(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + with mock.patch.object( + type(getattr(client.transport, close_name)), "close" + ) as close: + with client: + close.assert_not_called() + close.assert_called_once() + + +def test_client_ctx(): + transports = [ + "rest", + "grpc", + ] + for transport in transports: + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + # Test client calls underlying transport. + with mock.patch.object(type(client.transport), "close") as close: + close.assert_not_called() + with client: + pass + close.assert_called() + + +@pytest.mark.parametrize( + "client_class,transport_class", + [ + ( + GenerativeQuestionServiceClient, + transports.GenerativeQuestionServiceGrpcTransport, + ), + ( + GenerativeQuestionServiceAsyncClient, + transports.GenerativeQuestionServiceGrpcAsyncIOTransport, + ), + ], +) +def test_api_key_credentials(client_class, transport_class): + with mock.patch.object( + google.auth._default, "get_api_key_credentials", create=True + ) as get_api_key_credentials: + mock_cred = mock.Mock() + get_api_key_credentials.return_value = mock_cred + options = client_options.ClientOptions() + options.api_key = "api_key" + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options) + patched.assert_called_once_with( + credentials=mock_cred, + credentials_file=None, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) diff --git a/packages/google-cloud-retail/tests/unit/gapic/retail_v2alpha/test_generative_question_service.py b/packages/google-cloud-retail/tests/unit/gapic/retail_v2alpha/test_generative_question_service.py new file mode 100644 index 000000000000..de54573bd2e3 --- /dev/null +++ b/packages/google-cloud-retail/tests/unit/gapic/retail_v2alpha/test_generative_question_service.py @@ -0,0 +1,6449 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import os + +# try/except added for compatibility with python < 3.8 +try: + from unittest import mock + from unittest.mock import AsyncMock # pragma: NO COVER +except ImportError: # pragma: NO COVER + import mock + +from collections.abc import Iterable +import json +import math + +from google.api_core import gapic_v1, grpc_helpers, grpc_helpers_async, path_template +from google.api_core import api_core_version, client_options +from google.api_core import exceptions as core_exceptions +from google.api_core import retry as retries +import google.auth +from google.auth import credentials as ga_credentials +from google.auth.exceptions import MutualTLSChannelError +from google.cloud.location import locations_pb2 +from google.longrunning import operations_pb2 # type: ignore +from google.oauth2 import service_account +from google.protobuf import field_mask_pb2 # type: ignore +from google.protobuf import json_format +import grpc +from grpc.experimental import aio +from proto.marshal.rules import wrappers +from proto.marshal.rules.dates import DurationRule, TimestampRule +import pytest +from requests import PreparedRequest, Request, Response +from requests.sessions import Session + +from google.cloud.retail_v2alpha.services.generative_question_service import ( + GenerativeQuestionServiceAsyncClient, + GenerativeQuestionServiceClient, + transports, +) +from google.cloud.retail_v2alpha.types import ( + generative_question, + generative_question_service, +) + + +def client_cert_source_callback(): + return b"cert bytes", b"key bytes" + + +# If default endpoint is localhost, then default mtls endpoint will be the same. +# This method modifies the default endpoint so the client can produce a different +# mtls endpoint for endpoint testing purposes. +def modify_default_endpoint(client): + return ( + "foo.googleapis.com" + if ("localhost" in client.DEFAULT_ENDPOINT) + else client.DEFAULT_ENDPOINT + ) + + +# If default endpoint template is localhost, then default mtls endpoint will be the same. +# This method modifies the default endpoint template so the client can produce a different +# mtls endpoint for endpoint testing purposes. +def modify_default_endpoint_template(client): + return ( + "test.{UNIVERSE_DOMAIN}" + if ("localhost" in client._DEFAULT_ENDPOINT_TEMPLATE) + else client._DEFAULT_ENDPOINT_TEMPLATE + ) + + +def test__get_default_mtls_endpoint(): + api_endpoint = "example.googleapis.com" + api_mtls_endpoint = "example.mtls.googleapis.com" + sandbox_endpoint = "example.sandbox.googleapis.com" + sandbox_mtls_endpoint = "example.mtls.sandbox.googleapis.com" + non_googleapi = "api.example.com" + + assert GenerativeQuestionServiceClient._get_default_mtls_endpoint(None) is None + assert ( + GenerativeQuestionServiceClient._get_default_mtls_endpoint(api_endpoint) + == api_mtls_endpoint + ) + assert ( + GenerativeQuestionServiceClient._get_default_mtls_endpoint(api_mtls_endpoint) + == api_mtls_endpoint + ) + assert ( + GenerativeQuestionServiceClient._get_default_mtls_endpoint(sandbox_endpoint) + == sandbox_mtls_endpoint + ) + assert ( + GenerativeQuestionServiceClient._get_default_mtls_endpoint( + sandbox_mtls_endpoint + ) + == sandbox_mtls_endpoint + ) + assert ( + GenerativeQuestionServiceClient._get_default_mtls_endpoint(non_googleapi) + == non_googleapi + ) + + +def test__read_environment_variables(): + assert GenerativeQuestionServiceClient._read_environment_variables() == ( + False, + "auto", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "true"}): + assert GenerativeQuestionServiceClient._read_environment_variables() == ( + True, + "auto", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "false"}): + assert GenerativeQuestionServiceClient._read_environment_variables() == ( + False, + "auto", + None, + ) + + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"} + ): + with pytest.raises(ValueError) as excinfo: + GenerativeQuestionServiceClient._read_environment_variables() + assert ( + str(excinfo.value) + == "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): + assert GenerativeQuestionServiceClient._read_environment_variables() == ( + False, + "never", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): + assert GenerativeQuestionServiceClient._read_environment_variables() == ( + False, + "always", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "auto"}): + assert GenerativeQuestionServiceClient._read_environment_variables() == ( + False, + "auto", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "Unsupported"}): + with pytest.raises(MutualTLSChannelError) as excinfo: + GenerativeQuestionServiceClient._read_environment_variables() + assert ( + str(excinfo.value) + == "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`" + ) + + with mock.patch.dict(os.environ, {"GOOGLE_CLOUD_UNIVERSE_DOMAIN": "foo.com"}): + assert GenerativeQuestionServiceClient._read_environment_variables() == ( + False, + "auto", + "foo.com", + ) + + +def test__get_client_cert_source(): + mock_provided_cert_source = mock.Mock() + mock_default_cert_source = mock.Mock() + + assert GenerativeQuestionServiceClient._get_client_cert_source(None, False) is None + assert ( + GenerativeQuestionServiceClient._get_client_cert_source( + mock_provided_cert_source, False + ) + is None + ) + assert ( + GenerativeQuestionServiceClient._get_client_cert_source( + mock_provided_cert_source, True + ) + == mock_provided_cert_source + ) + + with mock.patch( + "google.auth.transport.mtls.has_default_client_cert_source", return_value=True + ): + with mock.patch( + "google.auth.transport.mtls.default_client_cert_source", + return_value=mock_default_cert_source, + ): + assert ( + GenerativeQuestionServiceClient._get_client_cert_source(None, True) + is mock_default_cert_source + ) + assert ( + GenerativeQuestionServiceClient._get_client_cert_source( + mock_provided_cert_source, "true" + ) + is mock_provided_cert_source + ) + + +@mock.patch.object( + GenerativeQuestionServiceClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(GenerativeQuestionServiceClient), +) +@mock.patch.object( + GenerativeQuestionServiceAsyncClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(GenerativeQuestionServiceAsyncClient), +) +def test__get_api_endpoint(): + api_override = "foo.com" + mock_client_cert_source = mock.Mock() + default_universe = GenerativeQuestionServiceClient._DEFAULT_UNIVERSE + default_endpoint = ( + GenerativeQuestionServiceClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=default_universe + ) + ) + mock_universe = "bar.com" + mock_endpoint = GenerativeQuestionServiceClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=mock_universe + ) + + assert ( + GenerativeQuestionServiceClient._get_api_endpoint( + api_override, mock_client_cert_source, default_universe, "always" + ) + == api_override + ) + assert ( + GenerativeQuestionServiceClient._get_api_endpoint( + None, mock_client_cert_source, default_universe, "auto" + ) + == GenerativeQuestionServiceClient.DEFAULT_MTLS_ENDPOINT + ) + assert ( + GenerativeQuestionServiceClient._get_api_endpoint( + None, None, default_universe, "auto" + ) + == default_endpoint + ) + assert ( + GenerativeQuestionServiceClient._get_api_endpoint( + None, None, default_universe, "always" + ) + == GenerativeQuestionServiceClient.DEFAULT_MTLS_ENDPOINT + ) + assert ( + GenerativeQuestionServiceClient._get_api_endpoint( + None, mock_client_cert_source, default_universe, "always" + ) + == GenerativeQuestionServiceClient.DEFAULT_MTLS_ENDPOINT + ) + assert ( + GenerativeQuestionServiceClient._get_api_endpoint( + None, None, mock_universe, "never" + ) + == mock_endpoint + ) + assert ( + GenerativeQuestionServiceClient._get_api_endpoint( + None, None, default_universe, "never" + ) + == default_endpoint + ) + + with pytest.raises(MutualTLSChannelError) as excinfo: + GenerativeQuestionServiceClient._get_api_endpoint( + None, mock_client_cert_source, mock_universe, "auto" + ) + assert ( + str(excinfo.value) + == "mTLS is not supported in any universe other than googleapis.com." + ) + + +def test__get_universe_domain(): + client_universe_domain = "foo.com" + universe_domain_env = "bar.com" + + assert ( + GenerativeQuestionServiceClient._get_universe_domain( + client_universe_domain, universe_domain_env + ) + == client_universe_domain + ) + assert ( + GenerativeQuestionServiceClient._get_universe_domain(None, universe_domain_env) + == universe_domain_env + ) + assert ( + GenerativeQuestionServiceClient._get_universe_domain(None, None) + == GenerativeQuestionServiceClient._DEFAULT_UNIVERSE + ) + + with pytest.raises(ValueError) as excinfo: + GenerativeQuestionServiceClient._get_universe_domain("", None) + assert str(excinfo.value) == "Universe Domain cannot be an empty string." + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name", + [ + ( + GenerativeQuestionServiceClient, + transports.GenerativeQuestionServiceGrpcTransport, + "grpc", + ), + ( + GenerativeQuestionServiceClient, + transports.GenerativeQuestionServiceRestTransport, + "rest", + ), + ], +) +def test__validate_universe_domain(client_class, transport_class, transport_name): + client = client_class( + transport=transport_class(credentials=ga_credentials.AnonymousCredentials()) + ) + assert client._validate_universe_domain() == True + + # Test the case when universe is already validated. + assert client._validate_universe_domain() == True + + if transport_name == "grpc": + # Test the case where credentials are provided by the + # `local_channel_credentials`. The default universes in both match. + channel = grpc.secure_channel( + "http://localhost/", grpc.local_channel_credentials() + ) + client = client_class(transport=transport_class(channel=channel)) + assert client._validate_universe_domain() == True + + # Test the case where credentials do not exist: e.g. a transport is provided + # with no credentials. Validation should still succeed because there is no + # mismatch with non-existent credentials. + channel = grpc.secure_channel( + "http://localhost/", grpc.local_channel_credentials() + ) + transport = transport_class(channel=channel) + transport._credentials = None + client = client_class(transport=transport) + assert client._validate_universe_domain() == True + + # TODO: This is needed to cater for older versions of google-auth + # Make this test unconditional once the minimum supported version of + # google-auth becomes 2.23.0 or higher. + google_auth_major, google_auth_minor = [ + int(part) for part in google.auth.__version__.split(".")[0:2] + ] + if google_auth_major > 2 or (google_auth_major == 2 and google_auth_minor >= 23): + credentials = ga_credentials.AnonymousCredentials() + credentials._universe_domain = "foo.com" + # Test the case when there is a universe mismatch from the credentials. + client = client_class(transport=transport_class(credentials=credentials)) + with pytest.raises(ValueError) as excinfo: + client._validate_universe_domain() + assert ( + str(excinfo.value) + == "The configured universe domain (googleapis.com) does not match the universe domain found in the credentials (foo.com). If you haven't configured the universe domain explicitly, `googleapis.com` is the default." + ) + + # Test the case when there is a universe mismatch from the client. + # + # TODO: Make this test unconditional once the minimum supported version of + # google-api-core becomes 2.15.0 or higher. + api_core_major, api_core_minor = [ + int(part) for part in api_core_version.__version__.split(".")[0:2] + ] + if api_core_major > 2 or (api_core_major == 2 and api_core_minor >= 15): + client = client_class( + client_options={"universe_domain": "bar.com"}, + transport=transport_class( + credentials=ga_credentials.AnonymousCredentials(), + ), + ) + with pytest.raises(ValueError) as excinfo: + client._validate_universe_domain() + assert ( + str(excinfo.value) + == "The configured universe domain (bar.com) does not match the universe domain found in the credentials (googleapis.com). If you haven't configured the universe domain explicitly, `googleapis.com` is the default." + ) + + # Test that ValueError is raised if universe_domain is provided via client options and credentials is None + with pytest.raises(ValueError): + client._compare_universes("foo.bar", None) + + +@pytest.mark.parametrize( + "client_class,transport_name", + [ + (GenerativeQuestionServiceClient, "grpc"), + (GenerativeQuestionServiceAsyncClient, "grpc_asyncio"), + (GenerativeQuestionServiceClient, "rest"), + ], +) +def test_generative_question_service_client_from_service_account_info( + client_class, transport_name +): + creds = ga_credentials.AnonymousCredentials() + with mock.patch.object( + service_account.Credentials, "from_service_account_info" + ) as factory: + factory.return_value = creds + info = {"valid": True} + client = client_class.from_service_account_info(info, transport=transport_name) + assert client.transport._credentials == creds + assert isinstance(client, client_class) + + assert client.transport._host == ( + "retail.googleapis.com:443" + if transport_name in ["grpc", "grpc_asyncio"] + else "https://retail.googleapis.com" + ) + + +@pytest.mark.parametrize( + "transport_class,transport_name", + [ + (transports.GenerativeQuestionServiceGrpcTransport, "grpc"), + (transports.GenerativeQuestionServiceGrpcAsyncIOTransport, "grpc_asyncio"), + (transports.GenerativeQuestionServiceRestTransport, "rest"), + ], +) +def test_generative_question_service_client_service_account_always_use_jwt( + transport_class, transport_name +): + with mock.patch.object( + service_account.Credentials, "with_always_use_jwt_access", create=True + ) as use_jwt: + creds = service_account.Credentials(None, None, None) + transport = transport_class(credentials=creds, always_use_jwt_access=True) + use_jwt.assert_called_once_with(True) + + with mock.patch.object( + service_account.Credentials, "with_always_use_jwt_access", create=True + ) as use_jwt: + creds = service_account.Credentials(None, None, None) + transport = transport_class(credentials=creds, always_use_jwt_access=False) + use_jwt.assert_not_called() + + +@pytest.mark.parametrize( + "client_class,transport_name", + [ + (GenerativeQuestionServiceClient, "grpc"), + (GenerativeQuestionServiceAsyncClient, "grpc_asyncio"), + (GenerativeQuestionServiceClient, "rest"), + ], +) +def test_generative_question_service_client_from_service_account_file( + client_class, transport_name +): + creds = ga_credentials.AnonymousCredentials() + with mock.patch.object( + service_account.Credentials, "from_service_account_file" + ) as factory: + factory.return_value = creds + client = client_class.from_service_account_file( + "dummy/file/path.json", transport=transport_name + ) + assert client.transport._credentials == creds + assert isinstance(client, client_class) + + client = client_class.from_service_account_json( + "dummy/file/path.json", transport=transport_name + ) + assert client.transport._credentials == creds + assert isinstance(client, client_class) + + assert client.transport._host == ( + "retail.googleapis.com:443" + if transport_name in ["grpc", "grpc_asyncio"] + else "https://retail.googleapis.com" + ) + + +def test_generative_question_service_client_get_transport_class(): + transport = GenerativeQuestionServiceClient.get_transport_class() + available_transports = [ + transports.GenerativeQuestionServiceGrpcTransport, + transports.GenerativeQuestionServiceRestTransport, + ] + assert transport in available_transports + + transport = GenerativeQuestionServiceClient.get_transport_class("grpc") + assert transport == transports.GenerativeQuestionServiceGrpcTransport + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name", + [ + ( + GenerativeQuestionServiceClient, + transports.GenerativeQuestionServiceGrpcTransport, + "grpc", + ), + ( + GenerativeQuestionServiceAsyncClient, + transports.GenerativeQuestionServiceGrpcAsyncIOTransport, + "grpc_asyncio", + ), + ( + GenerativeQuestionServiceClient, + transports.GenerativeQuestionServiceRestTransport, + "rest", + ), + ], +) +@mock.patch.object( + GenerativeQuestionServiceClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(GenerativeQuestionServiceClient), +) +@mock.patch.object( + GenerativeQuestionServiceAsyncClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(GenerativeQuestionServiceAsyncClient), +) +def test_generative_question_service_client_client_options( + client_class, transport_class, transport_name +): + # Check that if channel is provided we won't create a new one. + with mock.patch.object( + GenerativeQuestionServiceClient, "get_transport_class" + ) as gtc: + transport = transport_class(credentials=ga_credentials.AnonymousCredentials()) + client = client_class(transport=transport) + gtc.assert_not_called() + + # Check that if channel is provided via str we will create a new one. + with mock.patch.object( + GenerativeQuestionServiceClient, "get_transport_class" + ) as gtc: + client = client_class(transport=transport_name) + gtc.assert_called() + + # Check the case api_endpoint is provided. + options = client_options.ClientOptions(api_endpoint="squid.clam.whelk") + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(transport=transport_name, client_options=options) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host="squid.clam.whelk", + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT is + # "never". + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT is + # "always". + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client.DEFAULT_MTLS_ENDPOINT, + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT has + # unsupported value. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "Unsupported"}): + with pytest.raises(MutualTLSChannelError) as excinfo: + client = client_class(transport=transport_name) + assert ( + str(excinfo.value) + == "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`" + ) + + # Check the case GOOGLE_API_USE_CLIENT_CERTIFICATE has unsupported value. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"} + ): + with pytest.raises(ValueError) as excinfo: + client = client_class(transport=transport_name) + assert ( + str(excinfo.value) + == "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + + # Check the case quota_project_id is provided + options = client_options.ClientOptions(quota_project_id="octopus") + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options, transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id="octopus", + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + # Check the case api_endpoint is provided + options = client_options.ClientOptions( + api_audience="https://language.googleapis.com" + ) + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options, transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience="https://language.googleapis.com", + ) + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name,use_client_cert_env", + [ + ( + GenerativeQuestionServiceClient, + transports.GenerativeQuestionServiceGrpcTransport, + "grpc", + "true", + ), + ( + GenerativeQuestionServiceAsyncClient, + transports.GenerativeQuestionServiceGrpcAsyncIOTransport, + "grpc_asyncio", + "true", + ), + ( + GenerativeQuestionServiceClient, + transports.GenerativeQuestionServiceGrpcTransport, + "grpc", + "false", + ), + ( + GenerativeQuestionServiceAsyncClient, + transports.GenerativeQuestionServiceGrpcAsyncIOTransport, + "grpc_asyncio", + "false", + ), + ( + GenerativeQuestionServiceClient, + transports.GenerativeQuestionServiceRestTransport, + "rest", + "true", + ), + ( + GenerativeQuestionServiceClient, + transports.GenerativeQuestionServiceRestTransport, + "rest", + "false", + ), + ], +) +@mock.patch.object( + GenerativeQuestionServiceClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(GenerativeQuestionServiceClient), +) +@mock.patch.object( + GenerativeQuestionServiceAsyncClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(GenerativeQuestionServiceAsyncClient), +) +@mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "auto"}) +def test_generative_question_service_client_mtls_env_auto( + client_class, transport_class, transport_name, use_client_cert_env +): + # This tests the endpoint autoswitch behavior. Endpoint is autoswitched to the default + # mtls endpoint, if GOOGLE_API_USE_CLIENT_CERTIFICATE is "true" and client cert exists. + + # Check the case client_cert_source is provided. Whether client cert is used depends on + # GOOGLE_API_USE_CLIENT_CERTIFICATE value. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": use_client_cert_env} + ): + options = client_options.ClientOptions( + client_cert_source=client_cert_source_callback + ) + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options, transport=transport_name) + + if use_client_cert_env == "false": + expected_client_cert_source = None + expected_host = client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ) + else: + expected_client_cert_source = client_cert_source_callback + expected_host = client.DEFAULT_MTLS_ENDPOINT + + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=expected_host, + scopes=None, + client_cert_source_for_mtls=expected_client_cert_source, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + # Check the case ADC client cert is provided. Whether client cert is used depends on + # GOOGLE_API_USE_CLIENT_CERTIFICATE value. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": use_client_cert_env} + ): + with mock.patch.object(transport_class, "__init__") as patched: + with mock.patch( + "google.auth.transport.mtls.has_default_client_cert_source", + return_value=True, + ): + with mock.patch( + "google.auth.transport.mtls.default_client_cert_source", + return_value=client_cert_source_callback, + ): + if use_client_cert_env == "false": + expected_host = client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ) + expected_client_cert_source = None + else: + expected_host = client.DEFAULT_MTLS_ENDPOINT + expected_client_cert_source = client_cert_source_callback + + patched.return_value = None + client = client_class(transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=expected_host, + scopes=None, + client_cert_source_for_mtls=expected_client_cert_source, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + # Check the case client_cert_source and ADC client cert are not provided. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": use_client_cert_env} + ): + with mock.patch.object(transport_class, "__init__") as patched: + with mock.patch( + "google.auth.transport.mtls.has_default_client_cert_source", + return_value=False, + ): + patched.return_value = None + client = client_class(transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + +@pytest.mark.parametrize( + "client_class", + [GenerativeQuestionServiceClient, GenerativeQuestionServiceAsyncClient], +) +@mock.patch.object( + GenerativeQuestionServiceClient, + "DEFAULT_ENDPOINT", + modify_default_endpoint(GenerativeQuestionServiceClient), +) +@mock.patch.object( + GenerativeQuestionServiceAsyncClient, + "DEFAULT_ENDPOINT", + modify_default_endpoint(GenerativeQuestionServiceAsyncClient), +) +def test_generative_question_service_client_get_mtls_endpoint_and_cert_source( + client_class, +): + mock_client_cert_source = mock.Mock() + + # Test the case GOOGLE_API_USE_CLIENT_CERTIFICATE is "true". + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "true"}): + mock_api_endpoint = "foo" + options = client_options.ClientOptions( + client_cert_source=mock_client_cert_source, api_endpoint=mock_api_endpoint + ) + api_endpoint, cert_source = client_class.get_mtls_endpoint_and_cert_source( + options + ) + assert api_endpoint == mock_api_endpoint + assert cert_source == mock_client_cert_source + + # Test the case GOOGLE_API_USE_CLIENT_CERTIFICATE is "false". + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "false"}): + mock_client_cert_source = mock.Mock() + mock_api_endpoint = "foo" + options = client_options.ClientOptions( + client_cert_source=mock_client_cert_source, api_endpoint=mock_api_endpoint + ) + api_endpoint, cert_source = client_class.get_mtls_endpoint_and_cert_source( + options + ) + assert api_endpoint == mock_api_endpoint + assert cert_source is None + + # Test the case GOOGLE_API_USE_MTLS_ENDPOINT is "never". + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): + api_endpoint, cert_source = client_class.get_mtls_endpoint_and_cert_source() + assert api_endpoint == client_class.DEFAULT_ENDPOINT + assert cert_source is None + + # Test the case GOOGLE_API_USE_MTLS_ENDPOINT is "always". + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): + api_endpoint, cert_source = client_class.get_mtls_endpoint_and_cert_source() + assert api_endpoint == client_class.DEFAULT_MTLS_ENDPOINT + assert cert_source is None + + # Test the case GOOGLE_API_USE_MTLS_ENDPOINT is "auto" and default cert doesn't exist. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "true"}): + with mock.patch( + "google.auth.transport.mtls.has_default_client_cert_source", + return_value=False, + ): + api_endpoint, cert_source = client_class.get_mtls_endpoint_and_cert_source() + assert api_endpoint == client_class.DEFAULT_ENDPOINT + assert cert_source is None + + # Test the case GOOGLE_API_USE_MTLS_ENDPOINT is "auto" and default cert exists. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "true"}): + with mock.patch( + "google.auth.transport.mtls.has_default_client_cert_source", + return_value=True, + ): + with mock.patch( + "google.auth.transport.mtls.default_client_cert_source", + return_value=mock_client_cert_source, + ): + ( + api_endpoint, + cert_source, + ) = client_class.get_mtls_endpoint_and_cert_source() + assert api_endpoint == client_class.DEFAULT_MTLS_ENDPOINT + assert cert_source == mock_client_cert_source + + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT has + # unsupported value. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "Unsupported"}): + with pytest.raises(MutualTLSChannelError) as excinfo: + client_class.get_mtls_endpoint_and_cert_source() + + assert ( + str(excinfo.value) + == "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`" + ) + + # Check the case GOOGLE_API_USE_CLIENT_CERTIFICATE has unsupported value. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"} + ): + with pytest.raises(ValueError) as excinfo: + client_class.get_mtls_endpoint_and_cert_source() + + assert ( + str(excinfo.value) + == "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + + +@pytest.mark.parametrize( + "client_class", + [GenerativeQuestionServiceClient, GenerativeQuestionServiceAsyncClient], +) +@mock.patch.object( + GenerativeQuestionServiceClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(GenerativeQuestionServiceClient), +) +@mock.patch.object( + GenerativeQuestionServiceAsyncClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(GenerativeQuestionServiceAsyncClient), +) +def test_generative_question_service_client_client_api_endpoint(client_class): + mock_client_cert_source = client_cert_source_callback + api_override = "foo.com" + default_universe = GenerativeQuestionServiceClient._DEFAULT_UNIVERSE + default_endpoint = ( + GenerativeQuestionServiceClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=default_universe + ) + ) + mock_universe = "bar.com" + mock_endpoint = GenerativeQuestionServiceClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=mock_universe + ) + + # If ClientOptions.api_endpoint is set and GOOGLE_API_USE_CLIENT_CERTIFICATE="true", + # use ClientOptions.api_endpoint as the api endpoint regardless. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "true"}): + with mock.patch( + "google.auth.transport.requests.AuthorizedSession.configure_mtls_channel" + ): + options = client_options.ClientOptions( + client_cert_source=mock_client_cert_source, api_endpoint=api_override + ) + client = client_class( + client_options=options, + credentials=ga_credentials.AnonymousCredentials(), + ) + assert client.api_endpoint == api_override + + # If ClientOptions.api_endpoint is not set and GOOGLE_API_USE_MTLS_ENDPOINT="never", + # use the _DEFAULT_ENDPOINT_TEMPLATE populated with GDU as the api endpoint. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): + client = client_class(credentials=ga_credentials.AnonymousCredentials()) + assert client.api_endpoint == default_endpoint + + # If ClientOptions.api_endpoint is not set and GOOGLE_API_USE_MTLS_ENDPOINT="always", + # use the DEFAULT_MTLS_ENDPOINT as the api endpoint. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): + client = client_class(credentials=ga_credentials.AnonymousCredentials()) + assert client.api_endpoint == client_class.DEFAULT_MTLS_ENDPOINT + + # If ClientOptions.api_endpoint is not set, GOOGLE_API_USE_MTLS_ENDPOINT="auto" (default), + # GOOGLE_API_USE_CLIENT_CERTIFICATE="false" (default), default cert source doesn't exist, + # and ClientOptions.universe_domain="bar.com", + # use the _DEFAULT_ENDPOINT_TEMPLATE populated with universe domain as the api endpoint. + options = client_options.ClientOptions() + universe_exists = hasattr(options, "universe_domain") + if universe_exists: + options = client_options.ClientOptions(universe_domain=mock_universe) + client = client_class( + client_options=options, credentials=ga_credentials.AnonymousCredentials() + ) + else: + client = client_class( + client_options=options, credentials=ga_credentials.AnonymousCredentials() + ) + assert client.api_endpoint == ( + mock_endpoint if universe_exists else default_endpoint + ) + assert client.universe_domain == ( + mock_universe if universe_exists else default_universe + ) + + # If ClientOptions does not have a universe domain attribute and GOOGLE_API_USE_MTLS_ENDPOINT="never", + # use the _DEFAULT_ENDPOINT_TEMPLATE populated with GDU as the api endpoint. + options = client_options.ClientOptions() + if hasattr(options, "universe_domain"): + delattr(options, "universe_domain") + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): + client = client_class( + client_options=options, credentials=ga_credentials.AnonymousCredentials() + ) + assert client.api_endpoint == default_endpoint + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name", + [ + ( + GenerativeQuestionServiceClient, + transports.GenerativeQuestionServiceGrpcTransport, + "grpc", + ), + ( + GenerativeQuestionServiceAsyncClient, + transports.GenerativeQuestionServiceGrpcAsyncIOTransport, + "grpc_asyncio", + ), + ( + GenerativeQuestionServiceClient, + transports.GenerativeQuestionServiceRestTransport, + "rest", + ), + ], +) +def test_generative_question_service_client_client_options_scopes( + client_class, transport_class, transport_name +): + # Check the case scopes are provided. + options = client_options.ClientOptions( + scopes=["1", "2"], + ) + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options, transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), + scopes=["1", "2"], + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name,grpc_helpers", + [ + ( + GenerativeQuestionServiceClient, + transports.GenerativeQuestionServiceGrpcTransport, + "grpc", + grpc_helpers, + ), + ( + GenerativeQuestionServiceAsyncClient, + transports.GenerativeQuestionServiceGrpcAsyncIOTransport, + "grpc_asyncio", + grpc_helpers_async, + ), + ( + GenerativeQuestionServiceClient, + transports.GenerativeQuestionServiceRestTransport, + "rest", + None, + ), + ], +) +def test_generative_question_service_client_client_options_credentials_file( + client_class, transport_class, transport_name, grpc_helpers +): + # Check the case credentials file is provided. + options = client_options.ClientOptions(credentials_file="credentials.json") + + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options, transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file="credentials.json", + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + +def test_generative_question_service_client_client_options_from_dict(): + with mock.patch( + "google.cloud.retail_v2alpha.services.generative_question_service.transports.GenerativeQuestionServiceGrpcTransport.__init__" + ) as grpc_transport: + grpc_transport.return_value = None + client = GenerativeQuestionServiceClient( + client_options={"api_endpoint": "squid.clam.whelk"} + ) + grpc_transport.assert_called_once_with( + credentials=None, + credentials_file=None, + host="squid.clam.whelk", + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name,grpc_helpers", + [ + ( + GenerativeQuestionServiceClient, + transports.GenerativeQuestionServiceGrpcTransport, + "grpc", + grpc_helpers, + ), + ( + GenerativeQuestionServiceAsyncClient, + transports.GenerativeQuestionServiceGrpcAsyncIOTransport, + "grpc_asyncio", + grpc_helpers_async, + ), + ], +) +def test_generative_question_service_client_create_channel_credentials_file( + client_class, transport_class, transport_name, grpc_helpers +): + # Check the case credentials file is provided. + options = client_options.ClientOptions(credentials_file="credentials.json") + + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options, transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file="credentials.json", + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + # test that the credentials from file are saved and used as the credentials. + with mock.patch.object( + google.auth, "load_credentials_from_file", autospec=True + ) as load_creds, mock.patch.object( + google.auth, "default", autospec=True + ) as adc, mock.patch.object( + grpc_helpers, "create_channel" + ) as create_channel: + creds = ga_credentials.AnonymousCredentials() + file_creds = ga_credentials.AnonymousCredentials() + load_creds.return_value = (file_creds, None) + adc.return_value = (creds, None) + client = client_class(client_options=options, transport=transport_name) + create_channel.assert_called_with( + "retail.googleapis.com:443", + credentials=file_creds, + credentials_file=None, + quota_project_id=None, + default_scopes=("https://www.googleapis.com/auth/cloud-platform",), + scopes=None, + default_host="retail.googleapis.com", + ssl_credentials=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + +@pytest.mark.parametrize( + "request_type", + [ + generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest, + dict, + ], +) +def test_update_generative_questions_feature_config( + request_type, transport: str = "grpc" +): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_questions_feature_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = generative_question.GenerativeQuestionsFeatureConfig( + catalog="catalog_value", + feature_enabled=True, + minimum_products=1743, + ) + response = client.update_generative_questions_feature_config(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = ( + generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest() + ) + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, generative_question.GenerativeQuestionsFeatureConfig) + assert response.catalog == "catalog_value" + assert response.feature_enabled is True + assert response.minimum_products == 1743 + + +def test_update_generative_questions_feature_config_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_questions_feature_config), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.update_generative_questions_feature_config() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert ( + args[0] + == generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest() + ) + + +def test_update_generative_questions_feature_config_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = ( + generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest() + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_questions_feature_config), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.update_generative_questions_feature_config(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert ( + args[0] + == generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest() + ) + + +def test_update_generative_questions_feature_config_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.update_generative_questions_feature_config + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.update_generative_questions_feature_config + ] = mock_rpc + request = {} + client.update_generative_questions_feature_config(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.update_generative_questions_feature_config(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_update_generative_questions_feature_config_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_questions_feature_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question.GenerativeQuestionsFeatureConfig( + catalog="catalog_value", + feature_enabled=True, + minimum_products=1743, + ) + ) + response = await client.update_generative_questions_feature_config() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert ( + args[0] + == generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest() + ) + + +@pytest.mark.asyncio +async def test_update_generative_questions_feature_config_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.update_generative_questions_feature_config + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.AsyncMock() + mock_rpc.return_value = mock.Mock() + client._client._transport._wrapped_methods[ + client._client._transport.update_generative_questions_feature_config + ] = mock_rpc + + request = {} + await client.update_generative_questions_feature_config(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + await client.update_generative_questions_feature_config(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_update_generative_questions_feature_config_async( + transport: str = "grpc_asyncio", + request_type=generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest, +): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_questions_feature_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question.GenerativeQuestionsFeatureConfig( + catalog="catalog_value", + feature_enabled=True, + minimum_products=1743, + ) + ) + response = await client.update_generative_questions_feature_config(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = ( + generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest() + ) + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, generative_question.GenerativeQuestionsFeatureConfig) + assert response.catalog == "catalog_value" + assert response.feature_enabled is True + assert response.minimum_products == 1743 + + +@pytest.mark.asyncio +async def test_update_generative_questions_feature_config_async_from_dict(): + await test_update_generative_questions_feature_config_async(request_type=dict) + + +def test_update_generative_questions_feature_config_field_headers(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = ( + generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest() + ) + + request.generative_questions_feature_config.catalog = "catalog_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_questions_feature_config), "__call__" + ) as call: + call.return_value = generative_question.GenerativeQuestionsFeatureConfig() + client.update_generative_questions_feature_config(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "generative_questions_feature_config.catalog=catalog_value", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_update_generative_questions_feature_config_field_headers_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = ( + generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest() + ) + + request.generative_questions_feature_config.catalog = "catalog_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_questions_feature_config), "__call__" + ) as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question.GenerativeQuestionsFeatureConfig() + ) + await client.update_generative_questions_feature_config(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "generative_questions_feature_config.catalog=catalog_value", + ) in kw["metadata"] + + +def test_update_generative_questions_feature_config_flattened(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_questions_feature_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = generative_question.GenerativeQuestionsFeatureConfig() + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.update_generative_questions_feature_config( + generative_questions_feature_config=generative_question.GenerativeQuestionsFeatureConfig( + catalog="catalog_value" + ), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + arg = args[0].generative_questions_feature_config + mock_val = generative_question.GenerativeQuestionsFeatureConfig( + catalog="catalog_value" + ) + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val + + +def test_update_generative_questions_feature_config_flattened_error(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.update_generative_questions_feature_config( + generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest(), + generative_questions_feature_config=generative_question.GenerativeQuestionsFeatureConfig( + catalog="catalog_value" + ), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + +@pytest.mark.asyncio +async def test_update_generative_questions_feature_config_flattened_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_questions_feature_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = generative_question.GenerativeQuestionsFeatureConfig() + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question.GenerativeQuestionsFeatureConfig() + ) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.update_generative_questions_feature_config( + generative_questions_feature_config=generative_question.GenerativeQuestionsFeatureConfig( + catalog="catalog_value" + ), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + arg = args[0].generative_questions_feature_config + mock_val = generative_question.GenerativeQuestionsFeatureConfig( + catalog="catalog_value" + ) + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val + + +@pytest.mark.asyncio +async def test_update_generative_questions_feature_config_flattened_error_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + await client.update_generative_questions_feature_config( + generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest(), + generative_questions_feature_config=generative_question.GenerativeQuestionsFeatureConfig( + catalog="catalog_value" + ), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + +@pytest.mark.parametrize( + "request_type", + [ + generative_question_service.GetGenerativeQuestionsFeatureConfigRequest, + dict, + ], +) +def test_get_generative_questions_feature_config(request_type, transport: str = "grpc"): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.get_generative_questions_feature_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = generative_question.GenerativeQuestionsFeatureConfig( + catalog="catalog_value", + feature_enabled=True, + minimum_products=1743, + ) + response = client.get_generative_questions_feature_config(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = ( + generative_question_service.GetGenerativeQuestionsFeatureConfigRequest() + ) + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, generative_question.GenerativeQuestionsFeatureConfig) + assert response.catalog == "catalog_value" + assert response.feature_enabled is True + assert response.minimum_products == 1743 + + +def test_get_generative_questions_feature_config_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.get_generative_questions_feature_config), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.get_generative_questions_feature_config() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert ( + args[0] + == generative_question_service.GetGenerativeQuestionsFeatureConfigRequest() + ) + + +def test_get_generative_questions_feature_config_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = generative_question_service.GetGenerativeQuestionsFeatureConfigRequest( + catalog="catalog_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.get_generative_questions_feature_config), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.get_generative_questions_feature_config(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[ + 0 + ] == generative_question_service.GetGenerativeQuestionsFeatureConfigRequest( + catalog="catalog_value", + ) + + +def test_get_generative_questions_feature_config_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.get_generative_questions_feature_config + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.get_generative_questions_feature_config + ] = mock_rpc + request = {} + client.get_generative_questions_feature_config(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.get_generative_questions_feature_config(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_get_generative_questions_feature_config_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.get_generative_questions_feature_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question.GenerativeQuestionsFeatureConfig( + catalog="catalog_value", + feature_enabled=True, + minimum_products=1743, + ) + ) + response = await client.get_generative_questions_feature_config() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert ( + args[0] + == generative_question_service.GetGenerativeQuestionsFeatureConfigRequest() + ) + + +@pytest.mark.asyncio +async def test_get_generative_questions_feature_config_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.get_generative_questions_feature_config + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.AsyncMock() + mock_rpc.return_value = mock.Mock() + client._client._transport._wrapped_methods[ + client._client._transport.get_generative_questions_feature_config + ] = mock_rpc + + request = {} + await client.get_generative_questions_feature_config(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + await client.get_generative_questions_feature_config(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_get_generative_questions_feature_config_async( + transport: str = "grpc_asyncio", + request_type=generative_question_service.GetGenerativeQuestionsFeatureConfigRequest, +): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.get_generative_questions_feature_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question.GenerativeQuestionsFeatureConfig( + catalog="catalog_value", + feature_enabled=True, + minimum_products=1743, + ) + ) + response = await client.get_generative_questions_feature_config(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = ( + generative_question_service.GetGenerativeQuestionsFeatureConfigRequest() + ) + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, generative_question.GenerativeQuestionsFeatureConfig) + assert response.catalog == "catalog_value" + assert response.feature_enabled is True + assert response.minimum_products == 1743 + + +@pytest.mark.asyncio +async def test_get_generative_questions_feature_config_async_from_dict(): + await test_get_generative_questions_feature_config_async(request_type=dict) + + +def test_get_generative_questions_feature_config_field_headers(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = generative_question_service.GetGenerativeQuestionsFeatureConfigRequest() + + request.catalog = "catalog_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.get_generative_questions_feature_config), "__call__" + ) as call: + call.return_value = generative_question.GenerativeQuestionsFeatureConfig() + client.get_generative_questions_feature_config(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "catalog=catalog_value", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_get_generative_questions_feature_config_field_headers_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = generative_question_service.GetGenerativeQuestionsFeatureConfigRequest() + + request.catalog = "catalog_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.get_generative_questions_feature_config), "__call__" + ) as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question.GenerativeQuestionsFeatureConfig() + ) + await client.get_generative_questions_feature_config(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "catalog=catalog_value", + ) in kw["metadata"] + + +def test_get_generative_questions_feature_config_flattened(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.get_generative_questions_feature_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = generative_question.GenerativeQuestionsFeatureConfig() + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.get_generative_questions_feature_config( + catalog="catalog_value", + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + arg = args[0].catalog + mock_val = "catalog_value" + assert arg == mock_val + + +def test_get_generative_questions_feature_config_flattened_error(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.get_generative_questions_feature_config( + generative_question_service.GetGenerativeQuestionsFeatureConfigRequest(), + catalog="catalog_value", + ) + + +@pytest.mark.asyncio +async def test_get_generative_questions_feature_config_flattened_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.get_generative_questions_feature_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = generative_question.GenerativeQuestionsFeatureConfig() + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question.GenerativeQuestionsFeatureConfig() + ) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.get_generative_questions_feature_config( + catalog="catalog_value", + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + arg = args[0].catalog + mock_val = "catalog_value" + assert arg == mock_val + + +@pytest.mark.asyncio +async def test_get_generative_questions_feature_config_flattened_error_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + await client.get_generative_questions_feature_config( + generative_question_service.GetGenerativeQuestionsFeatureConfigRequest(), + catalog="catalog_value", + ) + + +@pytest.mark.parametrize( + "request_type", + [ + generative_question_service.ListGenerativeQuestionConfigsRequest, + dict, + ], +) +def test_list_generative_question_configs(request_type, transport: str = "grpc"): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_generative_question_configs), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = ( + generative_question_service.ListGenerativeQuestionConfigsResponse() + ) + response = client.list_generative_question_configs(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = generative_question_service.ListGenerativeQuestionConfigsRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance( + response, generative_question_service.ListGenerativeQuestionConfigsResponse + ) + + +def test_list_generative_question_configs_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_generative_question_configs), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.list_generative_question_configs() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert ( + args[0] + == generative_question_service.ListGenerativeQuestionConfigsRequest() + ) + + +def test_list_generative_question_configs_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = generative_question_service.ListGenerativeQuestionConfigsRequest( + parent="parent_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_generative_question_configs), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.list_generative_question_configs(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[ + 0 + ] == generative_question_service.ListGenerativeQuestionConfigsRequest( + parent="parent_value", + ) + + +def test_list_generative_question_configs_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.list_generative_question_configs + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.list_generative_question_configs + ] = mock_rpc + request = {} + client.list_generative_question_configs(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.list_generative_question_configs(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_list_generative_question_configs_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_generative_question_configs), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question_service.ListGenerativeQuestionConfigsResponse() + ) + response = await client.list_generative_question_configs() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert ( + args[0] + == generative_question_service.ListGenerativeQuestionConfigsRequest() + ) + + +@pytest.mark.asyncio +async def test_list_generative_question_configs_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.list_generative_question_configs + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.AsyncMock() + mock_rpc.return_value = mock.Mock() + client._client._transport._wrapped_methods[ + client._client._transport.list_generative_question_configs + ] = mock_rpc + + request = {} + await client.list_generative_question_configs(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + await client.list_generative_question_configs(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_list_generative_question_configs_async( + transport: str = "grpc_asyncio", + request_type=generative_question_service.ListGenerativeQuestionConfigsRequest, +): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_generative_question_configs), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question_service.ListGenerativeQuestionConfigsResponse() + ) + response = await client.list_generative_question_configs(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = generative_question_service.ListGenerativeQuestionConfigsRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance( + response, generative_question_service.ListGenerativeQuestionConfigsResponse + ) + + +@pytest.mark.asyncio +async def test_list_generative_question_configs_async_from_dict(): + await test_list_generative_question_configs_async(request_type=dict) + + +def test_list_generative_question_configs_field_headers(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = generative_question_service.ListGenerativeQuestionConfigsRequest() + + request.parent = "parent_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_generative_question_configs), "__call__" + ) as call: + call.return_value = ( + generative_question_service.ListGenerativeQuestionConfigsResponse() + ) + client.list_generative_question_configs(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "parent=parent_value", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_list_generative_question_configs_field_headers_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = generative_question_service.ListGenerativeQuestionConfigsRequest() + + request.parent = "parent_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_generative_question_configs), "__call__" + ) as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question_service.ListGenerativeQuestionConfigsResponse() + ) + await client.list_generative_question_configs(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "parent=parent_value", + ) in kw["metadata"] + + +def test_list_generative_question_configs_flattened(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_generative_question_configs), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = ( + generative_question_service.ListGenerativeQuestionConfigsResponse() + ) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.list_generative_question_configs( + parent="parent_value", + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + + +def test_list_generative_question_configs_flattened_error(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.list_generative_question_configs( + generative_question_service.ListGenerativeQuestionConfigsRequest(), + parent="parent_value", + ) + + +@pytest.mark.asyncio +async def test_list_generative_question_configs_flattened_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_generative_question_configs), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = ( + generative_question_service.ListGenerativeQuestionConfigsResponse() + ) + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question_service.ListGenerativeQuestionConfigsResponse() + ) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.list_generative_question_configs( + parent="parent_value", + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + + +@pytest.mark.asyncio +async def test_list_generative_question_configs_flattened_error_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + await client.list_generative_question_configs( + generative_question_service.ListGenerativeQuestionConfigsRequest(), + parent="parent_value", + ) + + +@pytest.mark.parametrize( + "request_type", + [ + generative_question_service.UpdateGenerativeQuestionConfigRequest, + dict, + ], +) +def test_update_generative_question_config(request_type, transport: str = "grpc"): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_question_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = generative_question.GenerativeQuestionConfig( + catalog="catalog_value", + facet="facet_value", + generated_question="generated_question_value", + final_question="final_question_value", + example_values=["example_values_value"], + frequency=0.978, + allowed_in_conversation=True, + ) + response = client.update_generative_question_config(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = generative_question_service.UpdateGenerativeQuestionConfigRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, generative_question.GenerativeQuestionConfig) + assert response.catalog == "catalog_value" + assert response.facet == "facet_value" + assert response.generated_question == "generated_question_value" + assert response.final_question == "final_question_value" + assert response.example_values == ["example_values_value"] + assert math.isclose(response.frequency, 0.978, rel_tol=1e-6) + assert response.allowed_in_conversation is True + + +def test_update_generative_question_config_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_question_config), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.update_generative_question_config() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert ( + args[0] + == generative_question_service.UpdateGenerativeQuestionConfigRequest() + ) + + +def test_update_generative_question_config_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = generative_question_service.UpdateGenerativeQuestionConfigRequest() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_question_config), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.update_generative_question_config(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert ( + args[0] + == generative_question_service.UpdateGenerativeQuestionConfigRequest() + ) + + +def test_update_generative_question_config_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.update_generative_question_config + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.update_generative_question_config + ] = mock_rpc + request = {} + client.update_generative_question_config(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.update_generative_question_config(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_update_generative_question_config_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_question_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question.GenerativeQuestionConfig( + catalog="catalog_value", + facet="facet_value", + generated_question="generated_question_value", + final_question="final_question_value", + example_values=["example_values_value"], + frequency=0.978, + allowed_in_conversation=True, + ) + ) + response = await client.update_generative_question_config() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert ( + args[0] + == generative_question_service.UpdateGenerativeQuestionConfigRequest() + ) + + +@pytest.mark.asyncio +async def test_update_generative_question_config_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.update_generative_question_config + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.AsyncMock() + mock_rpc.return_value = mock.Mock() + client._client._transport._wrapped_methods[ + client._client._transport.update_generative_question_config + ] = mock_rpc + + request = {} + await client.update_generative_question_config(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + await client.update_generative_question_config(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_update_generative_question_config_async( + transport: str = "grpc_asyncio", + request_type=generative_question_service.UpdateGenerativeQuestionConfigRequest, +): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_question_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question.GenerativeQuestionConfig( + catalog="catalog_value", + facet="facet_value", + generated_question="generated_question_value", + final_question="final_question_value", + example_values=["example_values_value"], + frequency=0.978, + allowed_in_conversation=True, + ) + ) + response = await client.update_generative_question_config(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = generative_question_service.UpdateGenerativeQuestionConfigRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, generative_question.GenerativeQuestionConfig) + assert response.catalog == "catalog_value" + assert response.facet == "facet_value" + assert response.generated_question == "generated_question_value" + assert response.final_question == "final_question_value" + assert response.example_values == ["example_values_value"] + assert math.isclose(response.frequency, 0.978, rel_tol=1e-6) + assert response.allowed_in_conversation is True + + +@pytest.mark.asyncio +async def test_update_generative_question_config_async_from_dict(): + await test_update_generative_question_config_async(request_type=dict) + + +def test_update_generative_question_config_field_headers(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = generative_question_service.UpdateGenerativeQuestionConfigRequest() + + request.generative_question_config.catalog = "catalog_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_question_config), "__call__" + ) as call: + call.return_value = generative_question.GenerativeQuestionConfig() + client.update_generative_question_config(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "generative_question_config.catalog=catalog_value", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_update_generative_question_config_field_headers_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = generative_question_service.UpdateGenerativeQuestionConfigRequest() + + request.generative_question_config.catalog = "catalog_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_question_config), "__call__" + ) as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question.GenerativeQuestionConfig() + ) + await client.update_generative_question_config(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "generative_question_config.catalog=catalog_value", + ) in kw["metadata"] + + +def test_update_generative_question_config_flattened(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_question_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = generative_question.GenerativeQuestionConfig() + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.update_generative_question_config( + generative_question_config=generative_question.GenerativeQuestionConfig( + catalog="catalog_value" + ), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + arg = args[0].generative_question_config + mock_val = generative_question.GenerativeQuestionConfig(catalog="catalog_value") + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val + + +def test_update_generative_question_config_flattened_error(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.update_generative_question_config( + generative_question_service.UpdateGenerativeQuestionConfigRequest(), + generative_question_config=generative_question.GenerativeQuestionConfig( + catalog="catalog_value" + ), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + +@pytest.mark.asyncio +async def test_update_generative_question_config_flattened_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_question_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = generative_question.GenerativeQuestionConfig() + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question.GenerativeQuestionConfig() + ) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.update_generative_question_config( + generative_question_config=generative_question.GenerativeQuestionConfig( + catalog="catalog_value" + ), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + arg = args[0].generative_question_config + mock_val = generative_question.GenerativeQuestionConfig(catalog="catalog_value") + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val + + +@pytest.mark.asyncio +async def test_update_generative_question_config_flattened_error_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + await client.update_generative_question_config( + generative_question_service.UpdateGenerativeQuestionConfigRequest(), + generative_question_config=generative_question.GenerativeQuestionConfig( + catalog="catalog_value" + ), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + +@pytest.mark.parametrize( + "request_type", + [ + generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest, + dict, + ], +) +def test_batch_update_generative_question_configs( + request_type, transport: str = "grpc" +): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.batch_update_generative_question_configs), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = ( + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse() + ) + response = client.batch_update_generative_question_configs(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = ( + generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest() + ) + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance( + response, + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse, + ) + + +def test_batch_update_generative_question_configs_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.batch_update_generative_question_configs), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.batch_update_generative_question_configs() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert ( + args[0] + == generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest() + ) + + +def test_batch_update_generative_question_configs_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest( + parent="parent_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.batch_update_generative_question_configs), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.batch_update_generative_question_configs(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[ + 0 + ] == generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest( + parent="parent_value", + ) + + +def test_batch_update_generative_question_configs_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.batch_update_generative_question_configs + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.batch_update_generative_question_configs + ] = mock_rpc + request = {} + client.batch_update_generative_question_configs(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.batch_update_generative_question_configs(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_batch_update_generative_question_configs_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.batch_update_generative_question_configs), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse() + ) + response = await client.batch_update_generative_question_configs() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert ( + args[0] + == generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest() + ) + + +@pytest.mark.asyncio +async def test_batch_update_generative_question_configs_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.batch_update_generative_question_configs + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.AsyncMock() + mock_rpc.return_value = mock.Mock() + client._client._transport._wrapped_methods[ + client._client._transport.batch_update_generative_question_configs + ] = mock_rpc + + request = {} + await client.batch_update_generative_question_configs(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + await client.batch_update_generative_question_configs(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_batch_update_generative_question_configs_async( + transport: str = "grpc_asyncio", + request_type=generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest, +): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.batch_update_generative_question_configs), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse() + ) + response = await client.batch_update_generative_question_configs(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = ( + generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest() + ) + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance( + response, + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse, + ) + + +@pytest.mark.asyncio +async def test_batch_update_generative_question_configs_async_from_dict(): + await test_batch_update_generative_question_configs_async(request_type=dict) + + +def test_batch_update_generative_question_configs_field_headers(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest() + + request.parent = "parent_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.batch_update_generative_question_configs), "__call__" + ) as call: + call.return_value = ( + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse() + ) + client.batch_update_generative_question_configs(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "parent=parent_value", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_batch_update_generative_question_configs_field_headers_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest() + + request.parent = "parent_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.batch_update_generative_question_configs), "__call__" + ) as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse() + ) + await client.batch_update_generative_question_configs(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "parent=parent_value", + ) in kw["metadata"] + + +def test_batch_update_generative_question_configs_flattened(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.batch_update_generative_question_configs), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = ( + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse() + ) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.batch_update_generative_question_configs( + parent="parent_value", + requests=[ + generative_question_service.UpdateGenerativeQuestionConfigRequest( + generative_question_config=generative_question.GenerativeQuestionConfig( + catalog="catalog_value" + ) + ) + ], + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].requests + mock_val = [ + generative_question_service.UpdateGenerativeQuestionConfigRequest( + generative_question_config=generative_question.GenerativeQuestionConfig( + catalog="catalog_value" + ) + ) + ] + assert arg == mock_val + + +def test_batch_update_generative_question_configs_flattened_error(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.batch_update_generative_question_configs( + generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest(), + parent="parent_value", + requests=[ + generative_question_service.UpdateGenerativeQuestionConfigRequest( + generative_question_config=generative_question.GenerativeQuestionConfig( + catalog="catalog_value" + ) + ) + ], + ) + + +@pytest.mark.asyncio +async def test_batch_update_generative_question_configs_flattened_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.batch_update_generative_question_configs), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = ( + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse() + ) + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse() + ) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.batch_update_generative_question_configs( + parent="parent_value", + requests=[ + generative_question_service.UpdateGenerativeQuestionConfigRequest( + generative_question_config=generative_question.GenerativeQuestionConfig( + catalog="catalog_value" + ) + ) + ], + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].requests + mock_val = [ + generative_question_service.UpdateGenerativeQuestionConfigRequest( + generative_question_config=generative_question.GenerativeQuestionConfig( + catalog="catalog_value" + ) + ) + ] + assert arg == mock_val + + +@pytest.mark.asyncio +async def test_batch_update_generative_question_configs_flattened_error_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + await client.batch_update_generative_question_configs( + generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest(), + parent="parent_value", + requests=[ + generative_question_service.UpdateGenerativeQuestionConfigRequest( + generative_question_config=generative_question.GenerativeQuestionConfig( + catalog="catalog_value" + ) + ) + ], + ) + + +@pytest.mark.parametrize( + "request_type", + [ + generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest, + dict, + ], +) +def test_update_generative_questions_feature_config_rest(request_type): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = { + "generative_questions_feature_config": { + "catalog": "projects/sample1/locations/sample2/catalogs/sample3" + } + } + request_init["generative_questions_feature_config"] = { + "catalog": "projects/sample1/locations/sample2/catalogs/sample3", + "feature_enabled": True, + "minimum_products": 1743, + } + # The version of a generated dependency at test runtime may differ from the version used during generation. + # Delete any fields which are not present in the current runtime dependency + # See https://github.com/googleapis/gapic-generator-python/issues/1748 + + # Determine if the message type is proto-plus or protobuf + test_field = generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest.meta.fields[ + "generative_questions_feature_config" + ] + + def get_message_fields(field): + # Given a field which is a message (composite type), return a list with + # all the fields of the message. + # If the field is not a composite type, return an empty list. + message_fields = [] + + if hasattr(field, "message") and field.message: + is_field_type_proto_plus_type = not hasattr(field.message, "DESCRIPTOR") + + if is_field_type_proto_plus_type: + message_fields = field.message.meta.fields.values() + # Add `# pragma: NO COVER` because there may not be any `*_pb2` field types + else: # pragma: NO COVER + message_fields = field.message.DESCRIPTOR.fields + return message_fields + + runtime_nested_fields = [ + (field.name, nested_field.name) + for field in get_message_fields(test_field) + for nested_field in get_message_fields(field) + ] + + subfields_not_in_runtime = [] + + # For each item in the sample request, create a list of sub fields which are not present at runtime + # Add `# pragma: NO COVER` because this test code will not run if all subfields are present at runtime + for field, value in request_init[ + "generative_questions_feature_config" + ].items(): # pragma: NO COVER + result = None + is_repeated = False + # For repeated fields + if isinstance(value, list) and len(value): + is_repeated = True + result = value[0] + # For fields where the type is another message + if isinstance(value, dict): + result = value + + if result and hasattr(result, "keys"): + for subfield in result.keys(): + if (field, subfield) not in runtime_nested_fields: + subfields_not_in_runtime.append( + { + "field": field, + "subfield": subfield, + "is_repeated": is_repeated, + } + ) + + # Remove fields from the sample request which are not present in the runtime version of the dependency + # Add `# pragma: NO COVER` because this test code will not run if all subfields are present at runtime + for subfield_to_delete in subfields_not_in_runtime: # pragma: NO COVER + field = subfield_to_delete.get("field") + field_repeated = subfield_to_delete.get("is_repeated") + subfield = subfield_to_delete.get("subfield") + if subfield: + if field_repeated: + for i in range( + 0, len(request_init["generative_questions_feature_config"][field]) + ): + del request_init["generative_questions_feature_config"][field][i][ + subfield + ] + else: + del request_init["generative_questions_feature_config"][field][subfield] + request = request_type(**request_init) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = generative_question.GenerativeQuestionsFeatureConfig( + catalog="catalog_value", + feature_enabled=True, + minimum_products=1743, + ) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = generative_question.GenerativeQuestionsFeatureConfig.pb( + return_value + ) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + response = client.update_generative_questions_feature_config(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, generative_question.GenerativeQuestionsFeatureConfig) + assert response.catalog == "catalog_value" + assert response.feature_enabled is True + assert response.minimum_products == 1743 + + +def test_update_generative_questions_feature_config_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.update_generative_questions_feature_config + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.update_generative_questions_feature_config + ] = mock_rpc + + request = {} + client.update_generative_questions_feature_config(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.update_generative_questions_feature_config(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_update_generative_questions_feature_config_rest_required_fields( + request_type=generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest, +): + transport_class = transports.GenerativeQuestionServiceRestTransport + + request_init = {} + request = request_type(**request_init) + pb_request = request_type.pb(request) + jsonified_request = json.loads( + json_format.MessageToJson(pb_request, use_integers_for_enums=False) + ) + + # verify fields with default values are dropped + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).update_generative_questions_feature_config._get_unset_required_fields( + jsonified_request + ) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).update_generative_questions_feature_config._get_unset_required_fields( + jsonified_request + ) + # Check that path parameters and body parameters are not mixing in. + assert not set(unset_fields) - set(("update_mask",)) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = generative_question.GenerativeQuestionsFeatureConfig() + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # We need to mock transcode() because providing default values + # for required fields will fail the real version if the http_options + # expect actual values for those fields. + with mock.patch.object(path_template, "transcode") as transcode: + # A uri without fields and an empty body will force all the + # request fields to show up in the query_params. + pb_request = request_type.pb(request) + transcode_result = { + "uri": "v1/sample_method", + "method": "patch", + "query_params": pb_request, + } + transcode_result["body"] = pb_request + transcode.return_value = transcode_result + + response_value = Response() + response_value.status_code = 200 + + # Convert return value to protobuf type + return_value = generative_question.GenerativeQuestionsFeatureConfig.pb( + return_value + ) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + response = client.update_generative_questions_feature_config(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_update_generative_questions_feature_config_rest_unset_required_fields(): + transport = transports.GenerativeQuestionServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = ( + transport.update_generative_questions_feature_config._get_unset_required_fields( + {} + ) + ) + assert set(unset_fields) == ( + set(("updateMask",)) & set(("generativeQuestionsFeatureConfig",)) + ) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_update_generative_questions_feature_config_rest_interceptors(null_interceptor): + transport = transports.GenerativeQuestionServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.GenerativeQuestionServiceRestInterceptor(), + ) + client = GenerativeQuestionServiceClient(transport=transport) + with mock.patch.object( + type(client.transport._session), "request" + ) as req, mock.patch.object( + path_template, "transcode" + ) as transcode, mock.patch.object( + transports.GenerativeQuestionServiceRestInterceptor, + "post_update_generative_questions_feature_config", + ) as post, mock.patch.object( + transports.GenerativeQuestionServiceRestInterceptor, + "pre_update_generative_questions_feature_config", + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest.pb( + generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest() + ) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = Response() + req.return_value.status_code = 200 + req.return_value.request = PreparedRequest() + req.return_value._content = ( + generative_question.GenerativeQuestionsFeatureConfig.to_json( + generative_question.GenerativeQuestionsFeatureConfig() + ) + ) + + request = ( + generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest() + ) + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = generative_question.GenerativeQuestionsFeatureConfig() + + client.update_generative_questions_feature_config( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_update_generative_questions_feature_config_rest_bad_request( + transport: str = "rest", + request_type=generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest, +): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = { + "generative_questions_feature_config": { + "catalog": "projects/sample1/locations/sample2/catalogs/sample3" + } + } + request = request_type(**request_init) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 400 + response_value.request = Request() + req.return_value = response_value + client.update_generative_questions_feature_config(request) + + +def test_update_generative_questions_feature_config_rest_flattened(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = generative_question.GenerativeQuestionsFeatureConfig() + + # get arguments that satisfy an http rule for this method + sample_request = { + "generative_questions_feature_config": { + "catalog": "projects/sample1/locations/sample2/catalogs/sample3" + } + } + + # get truthy value for each flattened field + mock_args = dict( + generative_questions_feature_config=generative_question.GenerativeQuestionsFeatureConfig( + catalog="catalog_value" + ), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + mock_args.update(sample_request) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = generative_question.GenerativeQuestionsFeatureConfig.pb( + return_value + ) + json_return_value = json_format.MessageToJson(return_value) + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + client.update_generative_questions_feature_config(**mock_args) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(req.mock_calls) == 1 + _, args, _ = req.mock_calls[0] + assert path_template.validate( + "%s/v2alpha/{generative_questions_feature_config.catalog=projects/*/locations/*/catalogs/*}/generativeQuestionFeature" + % client.transport._host, + args[1], + ) + + +def test_update_generative_questions_feature_config_rest_flattened_error( + transport: str = "rest", +): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.update_generative_questions_feature_config( + generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest(), + generative_questions_feature_config=generative_question.GenerativeQuestionsFeatureConfig( + catalog="catalog_value" + ), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + +def test_update_generative_questions_feature_config_rest_error(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + +@pytest.mark.parametrize( + "request_type", + [ + generative_question_service.GetGenerativeQuestionsFeatureConfigRequest, + dict, + ], +) +def test_get_generative_questions_feature_config_rest(request_type): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = {"catalog": "projects/sample1/locations/sample2/catalogs/sample3"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = generative_question.GenerativeQuestionsFeatureConfig( + catalog="catalog_value", + feature_enabled=True, + minimum_products=1743, + ) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = generative_question.GenerativeQuestionsFeatureConfig.pb( + return_value + ) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + response = client.get_generative_questions_feature_config(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, generative_question.GenerativeQuestionsFeatureConfig) + assert response.catalog == "catalog_value" + assert response.feature_enabled is True + assert response.minimum_products == 1743 + + +def test_get_generative_questions_feature_config_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.get_generative_questions_feature_config + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.get_generative_questions_feature_config + ] = mock_rpc + + request = {} + client.get_generative_questions_feature_config(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.get_generative_questions_feature_config(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_get_generative_questions_feature_config_rest_required_fields( + request_type=generative_question_service.GetGenerativeQuestionsFeatureConfigRequest, +): + transport_class = transports.GenerativeQuestionServiceRestTransport + + request_init = {} + request_init["catalog"] = "" + request = request_type(**request_init) + pb_request = request_type.pb(request) + jsonified_request = json.loads( + json_format.MessageToJson(pb_request, use_integers_for_enums=False) + ) + + # verify fields with default values are dropped + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).get_generative_questions_feature_config._get_unset_required_fields( + jsonified_request + ) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + jsonified_request["catalog"] = "catalog_value" + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).get_generative_questions_feature_config._get_unset_required_fields( + jsonified_request + ) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + assert "catalog" in jsonified_request + assert jsonified_request["catalog"] == "catalog_value" + + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = generative_question.GenerativeQuestionsFeatureConfig() + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # We need to mock transcode() because providing default values + # for required fields will fail the real version if the http_options + # expect actual values for those fields. + with mock.patch.object(path_template, "transcode") as transcode: + # A uri without fields and an empty body will force all the + # request fields to show up in the query_params. + pb_request = request_type.pb(request) + transcode_result = { + "uri": "v1/sample_method", + "method": "get", + "query_params": pb_request, + } + transcode.return_value = transcode_result + + response_value = Response() + response_value.status_code = 200 + + # Convert return value to protobuf type + return_value = generative_question.GenerativeQuestionsFeatureConfig.pb( + return_value + ) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + response = client.get_generative_questions_feature_config(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_get_generative_questions_feature_config_rest_unset_required_fields(): + transport = transports.GenerativeQuestionServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = ( + transport.get_generative_questions_feature_config._get_unset_required_fields({}) + ) + assert set(unset_fields) == (set(()) & set(("catalog",))) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_get_generative_questions_feature_config_rest_interceptors(null_interceptor): + transport = transports.GenerativeQuestionServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.GenerativeQuestionServiceRestInterceptor(), + ) + client = GenerativeQuestionServiceClient(transport=transport) + with mock.patch.object( + type(client.transport._session), "request" + ) as req, mock.patch.object( + path_template, "transcode" + ) as transcode, mock.patch.object( + transports.GenerativeQuestionServiceRestInterceptor, + "post_get_generative_questions_feature_config", + ) as post, mock.patch.object( + transports.GenerativeQuestionServiceRestInterceptor, + "pre_get_generative_questions_feature_config", + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = ( + generative_question_service.GetGenerativeQuestionsFeatureConfigRequest.pb( + generative_question_service.GetGenerativeQuestionsFeatureConfigRequest() + ) + ) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = Response() + req.return_value.status_code = 200 + req.return_value.request = PreparedRequest() + req.return_value._content = ( + generative_question.GenerativeQuestionsFeatureConfig.to_json( + generative_question.GenerativeQuestionsFeatureConfig() + ) + ) + + request = ( + generative_question_service.GetGenerativeQuestionsFeatureConfigRequest() + ) + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = generative_question.GenerativeQuestionsFeatureConfig() + + client.get_generative_questions_feature_config( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_get_generative_questions_feature_config_rest_bad_request( + transport: str = "rest", + request_type=generative_question_service.GetGenerativeQuestionsFeatureConfigRequest, +): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = {"catalog": "projects/sample1/locations/sample2/catalogs/sample3"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 400 + response_value.request = Request() + req.return_value = response_value + client.get_generative_questions_feature_config(request) + + +def test_get_generative_questions_feature_config_rest_flattened(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = generative_question.GenerativeQuestionsFeatureConfig() + + # get arguments that satisfy an http rule for this method + sample_request = { + "catalog": "projects/sample1/locations/sample2/catalogs/sample3" + } + + # get truthy value for each flattened field + mock_args = dict( + catalog="catalog_value", + ) + mock_args.update(sample_request) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = generative_question.GenerativeQuestionsFeatureConfig.pb( + return_value + ) + json_return_value = json_format.MessageToJson(return_value) + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + client.get_generative_questions_feature_config(**mock_args) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(req.mock_calls) == 1 + _, args, _ = req.mock_calls[0] + assert path_template.validate( + "%s/v2alpha/{catalog=projects/*/locations/*/catalogs/*}/generativeQuestionFeature" + % client.transport._host, + args[1], + ) + + +def test_get_generative_questions_feature_config_rest_flattened_error( + transport: str = "rest", +): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.get_generative_questions_feature_config( + generative_question_service.GetGenerativeQuestionsFeatureConfigRequest(), + catalog="catalog_value", + ) + + +def test_get_generative_questions_feature_config_rest_error(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + +@pytest.mark.parametrize( + "request_type", + [ + generative_question_service.ListGenerativeQuestionConfigsRequest, + dict, + ], +) +def test_list_generative_question_configs_rest(request_type): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = {"parent": "projects/sample1/locations/sample2/catalogs/sample3"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = ( + generative_question_service.ListGenerativeQuestionConfigsResponse() + ) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = ( + generative_question_service.ListGenerativeQuestionConfigsResponse.pb( + return_value + ) + ) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + response = client.list_generative_question_configs(request) + + # Establish that the response is the type that we expect. + assert isinstance( + response, generative_question_service.ListGenerativeQuestionConfigsResponse + ) + + +def test_list_generative_question_configs_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.list_generative_question_configs + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.list_generative_question_configs + ] = mock_rpc + + request = {} + client.list_generative_question_configs(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.list_generative_question_configs(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_list_generative_question_configs_rest_required_fields( + request_type=generative_question_service.ListGenerativeQuestionConfigsRequest, +): + transport_class = transports.GenerativeQuestionServiceRestTransport + + request_init = {} + request_init["parent"] = "" + request = request_type(**request_init) + pb_request = request_type.pb(request) + jsonified_request = json.loads( + json_format.MessageToJson(pb_request, use_integers_for_enums=False) + ) + + # verify fields with default values are dropped + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).list_generative_question_configs._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + jsonified_request["parent"] = "parent_value" + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).list_generative_question_configs._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + assert "parent" in jsonified_request + assert jsonified_request["parent"] == "parent_value" + + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = generative_question_service.ListGenerativeQuestionConfigsResponse() + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # We need to mock transcode() because providing default values + # for required fields will fail the real version if the http_options + # expect actual values for those fields. + with mock.patch.object(path_template, "transcode") as transcode: + # A uri without fields and an empty body will force all the + # request fields to show up in the query_params. + pb_request = request_type.pb(request) + transcode_result = { + "uri": "v1/sample_method", + "method": "get", + "query_params": pb_request, + } + transcode.return_value = transcode_result + + response_value = Response() + response_value.status_code = 200 + + # Convert return value to protobuf type + return_value = ( + generative_question_service.ListGenerativeQuestionConfigsResponse.pb( + return_value + ) + ) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + response = client.list_generative_question_configs(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_list_generative_question_configs_rest_unset_required_fields(): + transport = transports.GenerativeQuestionServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = ( + transport.list_generative_question_configs._get_unset_required_fields({}) + ) + assert set(unset_fields) == (set(()) & set(("parent",))) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_list_generative_question_configs_rest_interceptors(null_interceptor): + transport = transports.GenerativeQuestionServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.GenerativeQuestionServiceRestInterceptor(), + ) + client = GenerativeQuestionServiceClient(transport=transport) + with mock.patch.object( + type(client.transport._session), "request" + ) as req, mock.patch.object( + path_template, "transcode" + ) as transcode, mock.patch.object( + transports.GenerativeQuestionServiceRestInterceptor, + "post_list_generative_question_configs", + ) as post, mock.patch.object( + transports.GenerativeQuestionServiceRestInterceptor, + "pre_list_generative_question_configs", + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = ( + generative_question_service.ListGenerativeQuestionConfigsRequest.pb( + generative_question_service.ListGenerativeQuestionConfigsRequest() + ) + ) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = Response() + req.return_value.status_code = 200 + req.return_value.request = PreparedRequest() + req.return_value._content = ( + generative_question_service.ListGenerativeQuestionConfigsResponse.to_json( + generative_question_service.ListGenerativeQuestionConfigsResponse() + ) + ) + + request = generative_question_service.ListGenerativeQuestionConfigsRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = ( + generative_question_service.ListGenerativeQuestionConfigsResponse() + ) + + client.list_generative_question_configs( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_list_generative_question_configs_rest_bad_request( + transport: str = "rest", + request_type=generative_question_service.ListGenerativeQuestionConfigsRequest, +): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = {"parent": "projects/sample1/locations/sample2/catalogs/sample3"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 400 + response_value.request = Request() + req.return_value = response_value + client.list_generative_question_configs(request) + + +def test_list_generative_question_configs_rest_flattened(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = ( + generative_question_service.ListGenerativeQuestionConfigsResponse() + ) + + # get arguments that satisfy an http rule for this method + sample_request = { + "parent": "projects/sample1/locations/sample2/catalogs/sample3" + } + + # get truthy value for each flattened field + mock_args = dict( + parent="parent_value", + ) + mock_args.update(sample_request) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = ( + generative_question_service.ListGenerativeQuestionConfigsResponse.pb( + return_value + ) + ) + json_return_value = json_format.MessageToJson(return_value) + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + client.list_generative_question_configs(**mock_args) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(req.mock_calls) == 1 + _, args, _ = req.mock_calls[0] + assert path_template.validate( + "%s/v2alpha/{parent=projects/*/locations/*/catalogs/*}/generativeQuestions" + % client.transport._host, + args[1], + ) + + +def test_list_generative_question_configs_rest_flattened_error(transport: str = "rest"): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.list_generative_question_configs( + generative_question_service.ListGenerativeQuestionConfigsRequest(), + parent="parent_value", + ) + + +def test_list_generative_question_configs_rest_error(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + +@pytest.mark.parametrize( + "request_type", + [ + generative_question_service.UpdateGenerativeQuestionConfigRequest, + dict, + ], +) +def test_update_generative_question_config_rest(request_type): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = { + "generative_question_config": { + "catalog": "projects/sample1/locations/sample2/catalogs/sample3" + } + } + request_init["generative_question_config"] = { + "catalog": "projects/sample1/locations/sample2/catalogs/sample3", + "facet": "facet_value", + "generated_question": "generated_question_value", + "final_question": "final_question_value", + "example_values": ["example_values_value1", "example_values_value2"], + "frequency": 0.978, + "allowed_in_conversation": True, + } + # The version of a generated dependency at test runtime may differ from the version used during generation. + # Delete any fields which are not present in the current runtime dependency + # See https://github.com/googleapis/gapic-generator-python/issues/1748 + + # Determine if the message type is proto-plus or protobuf + test_field = ( + generative_question_service.UpdateGenerativeQuestionConfigRequest.meta.fields[ + "generative_question_config" + ] + ) + + def get_message_fields(field): + # Given a field which is a message (composite type), return a list with + # all the fields of the message. + # If the field is not a composite type, return an empty list. + message_fields = [] + + if hasattr(field, "message") and field.message: + is_field_type_proto_plus_type = not hasattr(field.message, "DESCRIPTOR") + + if is_field_type_proto_plus_type: + message_fields = field.message.meta.fields.values() + # Add `# pragma: NO COVER` because there may not be any `*_pb2` field types + else: # pragma: NO COVER + message_fields = field.message.DESCRIPTOR.fields + return message_fields + + runtime_nested_fields = [ + (field.name, nested_field.name) + for field in get_message_fields(test_field) + for nested_field in get_message_fields(field) + ] + + subfields_not_in_runtime = [] + + # For each item in the sample request, create a list of sub fields which are not present at runtime + # Add `# pragma: NO COVER` because this test code will not run if all subfields are present at runtime + for field, value in request_init[ + "generative_question_config" + ].items(): # pragma: NO COVER + result = None + is_repeated = False + # For repeated fields + if isinstance(value, list) and len(value): + is_repeated = True + result = value[0] + # For fields where the type is another message + if isinstance(value, dict): + result = value + + if result and hasattr(result, "keys"): + for subfield in result.keys(): + if (field, subfield) not in runtime_nested_fields: + subfields_not_in_runtime.append( + { + "field": field, + "subfield": subfield, + "is_repeated": is_repeated, + } + ) + + # Remove fields from the sample request which are not present in the runtime version of the dependency + # Add `# pragma: NO COVER` because this test code will not run if all subfields are present at runtime + for subfield_to_delete in subfields_not_in_runtime: # pragma: NO COVER + field = subfield_to_delete.get("field") + field_repeated = subfield_to_delete.get("is_repeated") + subfield = subfield_to_delete.get("subfield") + if subfield: + if field_repeated: + for i in range( + 0, len(request_init["generative_question_config"][field]) + ): + del request_init["generative_question_config"][field][i][subfield] + else: + del request_init["generative_question_config"][field][subfield] + request = request_type(**request_init) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = generative_question.GenerativeQuestionConfig( + catalog="catalog_value", + facet="facet_value", + generated_question="generated_question_value", + final_question="final_question_value", + example_values=["example_values_value"], + frequency=0.978, + allowed_in_conversation=True, + ) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = generative_question.GenerativeQuestionConfig.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + response = client.update_generative_question_config(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, generative_question.GenerativeQuestionConfig) + assert response.catalog == "catalog_value" + assert response.facet == "facet_value" + assert response.generated_question == "generated_question_value" + assert response.final_question == "final_question_value" + assert response.example_values == ["example_values_value"] + assert math.isclose(response.frequency, 0.978, rel_tol=1e-6) + assert response.allowed_in_conversation is True + + +def test_update_generative_question_config_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.update_generative_question_config + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.update_generative_question_config + ] = mock_rpc + + request = {} + client.update_generative_question_config(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.update_generative_question_config(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_update_generative_question_config_rest_required_fields( + request_type=generative_question_service.UpdateGenerativeQuestionConfigRequest, +): + transport_class = transports.GenerativeQuestionServiceRestTransport + + request_init = {} + request = request_type(**request_init) + pb_request = request_type.pb(request) + jsonified_request = json.loads( + json_format.MessageToJson(pb_request, use_integers_for_enums=False) + ) + + # verify fields with default values are dropped + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).update_generative_question_config._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).update_generative_question_config._get_unset_required_fields(jsonified_request) + # Check that path parameters and body parameters are not mixing in. + assert not set(unset_fields) - set(("update_mask",)) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = generative_question.GenerativeQuestionConfig() + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # We need to mock transcode() because providing default values + # for required fields will fail the real version if the http_options + # expect actual values for those fields. + with mock.patch.object(path_template, "transcode") as transcode: + # A uri without fields and an empty body will force all the + # request fields to show up in the query_params. + pb_request = request_type.pb(request) + transcode_result = { + "uri": "v1/sample_method", + "method": "patch", + "query_params": pb_request, + } + transcode_result["body"] = pb_request + transcode.return_value = transcode_result + + response_value = Response() + response_value.status_code = 200 + + # Convert return value to protobuf type + return_value = generative_question.GenerativeQuestionConfig.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + response = client.update_generative_question_config(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_update_generative_question_config_rest_unset_required_fields(): + transport = transports.GenerativeQuestionServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = ( + transport.update_generative_question_config._get_unset_required_fields({}) + ) + assert set(unset_fields) == ( + set(("updateMask",)) & set(("generativeQuestionConfig",)) + ) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_update_generative_question_config_rest_interceptors(null_interceptor): + transport = transports.GenerativeQuestionServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.GenerativeQuestionServiceRestInterceptor(), + ) + client = GenerativeQuestionServiceClient(transport=transport) + with mock.patch.object( + type(client.transport._session), "request" + ) as req, mock.patch.object( + path_template, "transcode" + ) as transcode, mock.patch.object( + transports.GenerativeQuestionServiceRestInterceptor, + "post_update_generative_question_config", + ) as post, mock.patch.object( + transports.GenerativeQuestionServiceRestInterceptor, + "pre_update_generative_question_config", + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = ( + generative_question_service.UpdateGenerativeQuestionConfigRequest.pb( + generative_question_service.UpdateGenerativeQuestionConfigRequest() + ) + ) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = Response() + req.return_value.status_code = 200 + req.return_value.request = PreparedRequest() + req.return_value._content = ( + generative_question.GenerativeQuestionConfig.to_json( + generative_question.GenerativeQuestionConfig() + ) + ) + + request = generative_question_service.UpdateGenerativeQuestionConfigRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = generative_question.GenerativeQuestionConfig() + + client.update_generative_question_config( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_update_generative_question_config_rest_bad_request( + transport: str = "rest", + request_type=generative_question_service.UpdateGenerativeQuestionConfigRequest, +): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = { + "generative_question_config": { + "catalog": "projects/sample1/locations/sample2/catalogs/sample3" + } + } + request = request_type(**request_init) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 400 + response_value.request = Request() + req.return_value = response_value + client.update_generative_question_config(request) + + +def test_update_generative_question_config_rest_flattened(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = generative_question.GenerativeQuestionConfig() + + # get arguments that satisfy an http rule for this method + sample_request = { + "generative_question_config": { + "catalog": "projects/sample1/locations/sample2/catalogs/sample3" + } + } + + # get truthy value for each flattened field + mock_args = dict( + generative_question_config=generative_question.GenerativeQuestionConfig( + catalog="catalog_value" + ), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + mock_args.update(sample_request) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = generative_question.GenerativeQuestionConfig.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + client.update_generative_question_config(**mock_args) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(req.mock_calls) == 1 + _, args, _ = req.mock_calls[0] + assert path_template.validate( + "%s/v2alpha/{generative_question_config.catalog=projects/*/locations/*/catalogs/*}/generativeQuestion" + % client.transport._host, + args[1], + ) + + +def test_update_generative_question_config_rest_flattened_error( + transport: str = "rest", +): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.update_generative_question_config( + generative_question_service.UpdateGenerativeQuestionConfigRequest(), + generative_question_config=generative_question.GenerativeQuestionConfig( + catalog="catalog_value" + ), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + +def test_update_generative_question_config_rest_error(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + +@pytest.mark.parametrize( + "request_type", + [ + generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest, + dict, + ], +) +def test_batch_update_generative_question_configs_rest(request_type): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = {"parent": "projects/sample1/locations/sample2/catalogs/sample3"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = ( + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse() + ) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = ( + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse.pb( + return_value + ) + ) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + response = client.batch_update_generative_question_configs(request) + + # Establish that the response is the type that we expect. + assert isinstance( + response, + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse, + ) + + +def test_batch_update_generative_question_configs_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.batch_update_generative_question_configs + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.batch_update_generative_question_configs + ] = mock_rpc + + request = {} + client.batch_update_generative_question_configs(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.batch_update_generative_question_configs(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_batch_update_generative_question_configs_rest_required_fields( + request_type=generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest, +): + transport_class = transports.GenerativeQuestionServiceRestTransport + + request_init = {} + request = request_type(**request_init) + pb_request = request_type.pb(request) + jsonified_request = json.loads( + json_format.MessageToJson(pb_request, use_integers_for_enums=False) + ) + + # verify fields with default values are dropped + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).batch_update_generative_question_configs._get_unset_required_fields( + jsonified_request + ) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).batch_update_generative_question_configs._get_unset_required_fields( + jsonified_request + ) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = ( + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse() + ) + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # We need to mock transcode() because providing default values + # for required fields will fail the real version if the http_options + # expect actual values for those fields. + with mock.patch.object(path_template, "transcode") as transcode: + # A uri without fields and an empty body will force all the + # request fields to show up in the query_params. + pb_request = request_type.pb(request) + transcode_result = { + "uri": "v1/sample_method", + "method": "post", + "query_params": pb_request, + } + transcode_result["body"] = pb_request + transcode.return_value = transcode_result + + response_value = Response() + response_value.status_code = 200 + + # Convert return value to protobuf type + return_value = generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse.pb( + return_value + ) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + response = client.batch_update_generative_question_configs(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_batch_update_generative_question_configs_rest_unset_required_fields(): + transport = transports.GenerativeQuestionServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = ( + transport.batch_update_generative_question_configs._get_unset_required_fields( + {} + ) + ) + assert set(unset_fields) == (set(()) & set(("requests",))) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_batch_update_generative_question_configs_rest_interceptors(null_interceptor): + transport = transports.GenerativeQuestionServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.GenerativeQuestionServiceRestInterceptor(), + ) + client = GenerativeQuestionServiceClient(transport=transport) + with mock.patch.object( + type(client.transport._session), "request" + ) as req, mock.patch.object( + path_template, "transcode" + ) as transcode, mock.patch.object( + transports.GenerativeQuestionServiceRestInterceptor, + "post_batch_update_generative_question_configs", + ) as post, mock.patch.object( + transports.GenerativeQuestionServiceRestInterceptor, + "pre_batch_update_generative_question_configs", + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest.pb( + generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest() + ) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = Response() + req.return_value.status_code = 200 + req.return_value.request = PreparedRequest() + req.return_value._content = generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse.to_json( + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse() + ) + + request = ( + generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest() + ) + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = ( + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse() + ) + + client.batch_update_generative_question_configs( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_batch_update_generative_question_configs_rest_bad_request( + transport: str = "rest", + request_type=generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest, +): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = {"parent": "projects/sample1/locations/sample2/catalogs/sample3"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 400 + response_value.request = Request() + req.return_value = response_value + client.batch_update_generative_question_configs(request) + + +def test_batch_update_generative_question_configs_rest_flattened(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = ( + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse() + ) + + # get arguments that satisfy an http rule for this method + sample_request = { + "parent": "projects/sample1/locations/sample2/catalogs/sample3" + } + + # get truthy value for each flattened field + mock_args = dict( + parent="parent_value", + requests=[ + generative_question_service.UpdateGenerativeQuestionConfigRequest( + generative_question_config=generative_question.GenerativeQuestionConfig( + catalog="catalog_value" + ) + ) + ], + ) + mock_args.update(sample_request) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = ( + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse.pb( + return_value + ) + ) + json_return_value = json_format.MessageToJson(return_value) + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + client.batch_update_generative_question_configs(**mock_args) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(req.mock_calls) == 1 + _, args, _ = req.mock_calls[0] + assert path_template.validate( + "%s/v2alpha/{parent=projects/*/locations/*/catalogs/*}/generativeQuestion:batchUpdate" + % client.transport._host, + args[1], + ) + + +def test_batch_update_generative_question_configs_rest_flattened_error( + transport: str = "rest", +): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.batch_update_generative_question_configs( + generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest(), + parent="parent_value", + requests=[ + generative_question_service.UpdateGenerativeQuestionConfigRequest( + generative_question_config=generative_question.GenerativeQuestionConfig( + catalog="catalog_value" + ) + ) + ], + ) + + +def test_batch_update_generative_question_configs_rest_error(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + +def test_credentials_transport_error(): + # It is an error to provide credentials and a transport instance. + transport = transports.GenerativeQuestionServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + with pytest.raises(ValueError): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # It is an error to provide a credentials file and a transport instance. + transport = transports.GenerativeQuestionServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + with pytest.raises(ValueError): + client = GenerativeQuestionServiceClient( + client_options={"credentials_file": "credentials.json"}, + transport=transport, + ) + + # It is an error to provide an api_key and a transport instance. + transport = transports.GenerativeQuestionServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + options = client_options.ClientOptions() + options.api_key = "api_key" + with pytest.raises(ValueError): + client = GenerativeQuestionServiceClient( + client_options=options, + transport=transport, + ) + + # It is an error to provide an api_key and a credential. + options = client_options.ClientOptions() + options.api_key = "api_key" + with pytest.raises(ValueError): + client = GenerativeQuestionServiceClient( + client_options=options, credentials=ga_credentials.AnonymousCredentials() + ) + + # It is an error to provide scopes and a transport instance. + transport = transports.GenerativeQuestionServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + with pytest.raises(ValueError): + client = GenerativeQuestionServiceClient( + client_options={"scopes": ["1", "2"]}, + transport=transport, + ) + + +def test_transport_instance(): + # A client may be instantiated with a custom transport instance. + transport = transports.GenerativeQuestionServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + client = GenerativeQuestionServiceClient(transport=transport) + assert client.transport is transport + + +def test_transport_get_channel(): + # A client may be instantiated with a custom transport instance. + transport = transports.GenerativeQuestionServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + channel = transport.grpc_channel + assert channel + + transport = transports.GenerativeQuestionServiceGrpcAsyncIOTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + channel = transport.grpc_channel + assert channel + + +@pytest.mark.parametrize( + "transport_class", + [ + transports.GenerativeQuestionServiceGrpcTransport, + transports.GenerativeQuestionServiceGrpcAsyncIOTransport, + transports.GenerativeQuestionServiceRestTransport, + ], +) +def test_transport_adc(transport_class): + # Test default credentials are used if not provided. + with mock.patch.object(google.auth, "default") as adc: + adc.return_value = (ga_credentials.AnonymousCredentials(), None) + transport_class() + adc.assert_called_once() + + +@pytest.mark.parametrize( + "transport_name", + [ + "grpc", + "rest", + ], +) +def test_transport_kind(transport_name): + transport = GenerativeQuestionServiceClient.get_transport_class(transport_name)( + credentials=ga_credentials.AnonymousCredentials(), + ) + assert transport.kind == transport_name + + +def test_transport_grpc_default(): + # A client should use the gRPC transport by default. + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + assert isinstance( + client.transport, + transports.GenerativeQuestionServiceGrpcTransport, + ) + + +def test_generative_question_service_base_transport_error(): + # Passing both a credentials object and credentials_file should raise an error + with pytest.raises(core_exceptions.DuplicateCredentialArgs): + transport = transports.GenerativeQuestionServiceTransport( + credentials=ga_credentials.AnonymousCredentials(), + credentials_file="credentials.json", + ) + + +def test_generative_question_service_base_transport(): + # Instantiate the base transport. + with mock.patch( + "google.cloud.retail_v2alpha.services.generative_question_service.transports.GenerativeQuestionServiceTransport.__init__" + ) as Transport: + Transport.return_value = None + transport = transports.GenerativeQuestionServiceTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Every method on the transport should just blindly + # raise NotImplementedError. + methods = ( + "update_generative_questions_feature_config", + "get_generative_questions_feature_config", + "list_generative_question_configs", + "update_generative_question_config", + "batch_update_generative_question_configs", + "get_operation", + "list_operations", + ) + for method in methods: + with pytest.raises(NotImplementedError): + getattr(transport, method)(request=object()) + + with pytest.raises(NotImplementedError): + transport.close() + + # Catch all for all remaining methods and properties + remainder = [ + "kind", + ] + for r in remainder: + with pytest.raises(NotImplementedError): + getattr(transport, r)() + + +def test_generative_question_service_base_transport_with_credentials_file(): + # Instantiate the base transport with a credentials file + with mock.patch.object( + google.auth, "load_credentials_from_file", autospec=True + ) as load_creds, mock.patch( + "google.cloud.retail_v2alpha.services.generative_question_service.transports.GenerativeQuestionServiceTransport._prep_wrapped_messages" + ) as Transport: + Transport.return_value = None + load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) + transport = transports.GenerativeQuestionServiceTransport( + credentials_file="credentials.json", + quota_project_id="octopus", + ) + load_creds.assert_called_once_with( + "credentials.json", + scopes=None, + default_scopes=("https://www.googleapis.com/auth/cloud-platform",), + quota_project_id="octopus", + ) + + +def test_generative_question_service_base_transport_with_adc(): + # Test the default credentials are used if credentials and credentials_file are None. + with mock.patch.object(google.auth, "default", autospec=True) as adc, mock.patch( + "google.cloud.retail_v2alpha.services.generative_question_service.transports.GenerativeQuestionServiceTransport._prep_wrapped_messages" + ) as Transport: + Transport.return_value = None + adc.return_value = (ga_credentials.AnonymousCredentials(), None) + transport = transports.GenerativeQuestionServiceTransport() + adc.assert_called_once() + + +def test_generative_question_service_auth_adc(): + # If no credentials are provided, we should use ADC credentials. + with mock.patch.object(google.auth, "default", autospec=True) as adc: + adc.return_value = (ga_credentials.AnonymousCredentials(), None) + GenerativeQuestionServiceClient() + adc.assert_called_once_with( + scopes=None, + default_scopes=("https://www.googleapis.com/auth/cloud-platform",), + quota_project_id=None, + ) + + +@pytest.mark.parametrize( + "transport_class", + [ + transports.GenerativeQuestionServiceGrpcTransport, + transports.GenerativeQuestionServiceGrpcAsyncIOTransport, + ], +) +def test_generative_question_service_transport_auth_adc(transport_class): + # If credentials and host are not provided, the transport class should use + # ADC credentials. + with mock.patch.object(google.auth, "default", autospec=True) as adc: + adc.return_value = (ga_credentials.AnonymousCredentials(), None) + transport_class(quota_project_id="octopus", scopes=["1", "2"]) + adc.assert_called_once_with( + scopes=["1", "2"], + default_scopes=("https://www.googleapis.com/auth/cloud-platform",), + quota_project_id="octopus", + ) + + +@pytest.mark.parametrize( + "transport_class", + [ + transports.GenerativeQuestionServiceGrpcTransport, + transports.GenerativeQuestionServiceGrpcAsyncIOTransport, + transports.GenerativeQuestionServiceRestTransport, + ], +) +def test_generative_question_service_transport_auth_gdch_credentials(transport_class): + host = "https://language.com" + api_audience_tests = [None, "https://language2.com"] + api_audience_expect = [host, "https://language2.com"] + for t, e in zip(api_audience_tests, api_audience_expect): + with mock.patch.object(google.auth, "default", autospec=True) as adc: + gdch_mock = mock.MagicMock() + type(gdch_mock).with_gdch_audience = mock.PropertyMock( + return_value=gdch_mock + ) + adc.return_value = (gdch_mock, None) + transport_class(host=host, api_audience=t) + gdch_mock.with_gdch_audience.assert_called_once_with(e) + + +@pytest.mark.parametrize( + "transport_class,grpc_helpers", + [ + (transports.GenerativeQuestionServiceGrpcTransport, grpc_helpers), + (transports.GenerativeQuestionServiceGrpcAsyncIOTransport, grpc_helpers_async), + ], +) +def test_generative_question_service_transport_create_channel( + transport_class, grpc_helpers +): + # If credentials and host are not provided, the transport class should use + # ADC credentials. + with mock.patch.object( + google.auth, "default", autospec=True + ) as adc, mock.patch.object( + grpc_helpers, "create_channel", autospec=True + ) as create_channel: + creds = ga_credentials.AnonymousCredentials() + adc.return_value = (creds, None) + transport_class(quota_project_id="octopus", scopes=["1", "2"]) + + create_channel.assert_called_with( + "retail.googleapis.com:443", + credentials=creds, + credentials_file=None, + quota_project_id="octopus", + default_scopes=("https://www.googleapis.com/auth/cloud-platform",), + scopes=["1", "2"], + default_host="retail.googleapis.com", + ssl_credentials=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + +@pytest.mark.parametrize( + "transport_class", + [ + transports.GenerativeQuestionServiceGrpcTransport, + transports.GenerativeQuestionServiceGrpcAsyncIOTransport, + ], +) +def test_generative_question_service_grpc_transport_client_cert_source_for_mtls( + transport_class, +): + cred = ga_credentials.AnonymousCredentials() + + # Check ssl_channel_credentials is used if provided. + with mock.patch.object(transport_class, "create_channel") as mock_create_channel: + mock_ssl_channel_creds = mock.Mock() + transport_class( + host="squid.clam.whelk", + credentials=cred, + ssl_channel_credentials=mock_ssl_channel_creds, + ) + mock_create_channel.assert_called_once_with( + "squid.clam.whelk:443", + credentials=cred, + credentials_file=None, + scopes=None, + ssl_credentials=mock_ssl_channel_creds, + quota_project_id=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Check if ssl_channel_credentials is not provided, then client_cert_source_for_mtls + # is used. + with mock.patch.object(transport_class, "create_channel", return_value=mock.Mock()): + with mock.patch("grpc.ssl_channel_credentials") as mock_ssl_cred: + transport_class( + credentials=cred, + client_cert_source_for_mtls=client_cert_source_callback, + ) + expected_cert, expected_key = client_cert_source_callback() + mock_ssl_cred.assert_called_once_with( + certificate_chain=expected_cert, private_key=expected_key + ) + + +def test_generative_question_service_http_transport_client_cert_source_for_mtls(): + cred = ga_credentials.AnonymousCredentials() + with mock.patch( + "google.auth.transport.requests.AuthorizedSession.configure_mtls_channel" + ) as mock_configure_mtls_channel: + transports.GenerativeQuestionServiceRestTransport( + credentials=cred, client_cert_source_for_mtls=client_cert_source_callback + ) + mock_configure_mtls_channel.assert_called_once_with(client_cert_source_callback) + + +@pytest.mark.parametrize( + "transport_name", + [ + "grpc", + "grpc_asyncio", + "rest", + ], +) +def test_generative_question_service_host_no_port(transport_name): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + client_options=client_options.ClientOptions( + api_endpoint="retail.googleapis.com" + ), + transport=transport_name, + ) + assert client.transport._host == ( + "retail.googleapis.com:443" + if transport_name in ["grpc", "grpc_asyncio"] + else "https://retail.googleapis.com" + ) + + +@pytest.mark.parametrize( + "transport_name", + [ + "grpc", + "grpc_asyncio", + "rest", + ], +) +def test_generative_question_service_host_with_port(transport_name): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + client_options=client_options.ClientOptions( + api_endpoint="retail.googleapis.com:8000" + ), + transport=transport_name, + ) + assert client.transport._host == ( + "retail.googleapis.com:8000" + if transport_name in ["grpc", "grpc_asyncio"] + else "https://retail.googleapis.com:8000" + ) + + +@pytest.mark.parametrize( + "transport_name", + [ + "rest", + ], +) +def test_generative_question_service_client_transport_session_collision(transport_name): + creds1 = ga_credentials.AnonymousCredentials() + creds2 = ga_credentials.AnonymousCredentials() + client1 = GenerativeQuestionServiceClient( + credentials=creds1, + transport=transport_name, + ) + client2 = GenerativeQuestionServiceClient( + credentials=creds2, + transport=transport_name, + ) + session1 = client1.transport.update_generative_questions_feature_config._session + session2 = client2.transport.update_generative_questions_feature_config._session + assert session1 != session2 + session1 = client1.transport.get_generative_questions_feature_config._session + session2 = client2.transport.get_generative_questions_feature_config._session + assert session1 != session2 + session1 = client1.transport.list_generative_question_configs._session + session2 = client2.transport.list_generative_question_configs._session + assert session1 != session2 + session1 = client1.transport.update_generative_question_config._session + session2 = client2.transport.update_generative_question_config._session + assert session1 != session2 + session1 = client1.transport.batch_update_generative_question_configs._session + session2 = client2.transport.batch_update_generative_question_configs._session + assert session1 != session2 + + +def test_generative_question_service_grpc_transport_channel(): + channel = grpc.secure_channel("http://localhost/", grpc.local_channel_credentials()) + + # Check that channel is used if provided. + transport = transports.GenerativeQuestionServiceGrpcTransport( + host="squid.clam.whelk", + channel=channel, + ) + assert transport.grpc_channel == channel + assert transport._host == "squid.clam.whelk:443" + assert transport._ssl_channel_credentials == None + + +def test_generative_question_service_grpc_asyncio_transport_channel(): + channel = aio.secure_channel("http://localhost/", grpc.local_channel_credentials()) + + # Check that channel is used if provided. + transport = transports.GenerativeQuestionServiceGrpcAsyncIOTransport( + host="squid.clam.whelk", + channel=channel, + ) + assert transport.grpc_channel == channel + assert transport._host == "squid.clam.whelk:443" + assert transport._ssl_channel_credentials == None + + +# Remove this test when deprecated arguments (api_mtls_endpoint, client_cert_source) are +# removed from grpc/grpc_asyncio transport constructor. +@pytest.mark.parametrize( + "transport_class", + [ + transports.GenerativeQuestionServiceGrpcTransport, + transports.GenerativeQuestionServiceGrpcAsyncIOTransport, + ], +) +def test_generative_question_service_transport_channel_mtls_with_client_cert_source( + transport_class, +): + with mock.patch( + "grpc.ssl_channel_credentials", autospec=True + ) as grpc_ssl_channel_cred: + with mock.patch.object( + transport_class, "create_channel" + ) as grpc_create_channel: + mock_ssl_cred = mock.Mock() + grpc_ssl_channel_cred.return_value = mock_ssl_cred + + mock_grpc_channel = mock.Mock() + grpc_create_channel.return_value = mock_grpc_channel + + cred = ga_credentials.AnonymousCredentials() + with pytest.warns(DeprecationWarning): + with mock.patch.object(google.auth, "default") as adc: + adc.return_value = (cred, None) + transport = transport_class( + host="squid.clam.whelk", + api_mtls_endpoint="mtls.squid.clam.whelk", + client_cert_source=client_cert_source_callback, + ) + adc.assert_called_once() + + grpc_ssl_channel_cred.assert_called_once_with( + certificate_chain=b"cert bytes", private_key=b"key bytes" + ) + grpc_create_channel.assert_called_once_with( + "mtls.squid.clam.whelk:443", + credentials=cred, + credentials_file=None, + scopes=None, + ssl_credentials=mock_ssl_cred, + quota_project_id=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + assert transport.grpc_channel == mock_grpc_channel + assert transport._ssl_channel_credentials == mock_ssl_cred + + +# Remove this test when deprecated arguments (api_mtls_endpoint, client_cert_source) are +# removed from grpc/grpc_asyncio transport constructor. +@pytest.mark.parametrize( + "transport_class", + [ + transports.GenerativeQuestionServiceGrpcTransport, + transports.GenerativeQuestionServiceGrpcAsyncIOTransport, + ], +) +def test_generative_question_service_transport_channel_mtls_with_adc(transport_class): + mock_ssl_cred = mock.Mock() + with mock.patch.multiple( + "google.auth.transport.grpc.SslCredentials", + __init__=mock.Mock(return_value=None), + ssl_credentials=mock.PropertyMock(return_value=mock_ssl_cred), + ): + with mock.patch.object( + transport_class, "create_channel" + ) as grpc_create_channel: + mock_grpc_channel = mock.Mock() + grpc_create_channel.return_value = mock_grpc_channel + mock_cred = mock.Mock() + + with pytest.warns(DeprecationWarning): + transport = transport_class( + host="squid.clam.whelk", + credentials=mock_cred, + api_mtls_endpoint="mtls.squid.clam.whelk", + client_cert_source=None, + ) + + grpc_create_channel.assert_called_once_with( + "mtls.squid.clam.whelk:443", + credentials=mock_cred, + credentials_file=None, + scopes=None, + ssl_credentials=mock_ssl_cred, + quota_project_id=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + assert transport.grpc_channel == mock_grpc_channel + + +def test_catalog_path(): + project = "squid" + location = "clam" + catalog = "whelk" + expected = "projects/{project}/locations/{location}/catalogs/{catalog}".format( + project=project, + location=location, + catalog=catalog, + ) + actual = GenerativeQuestionServiceClient.catalog_path(project, location, catalog) + assert expected == actual + + +def test_parse_catalog_path(): + expected = { + "project": "octopus", + "location": "oyster", + "catalog": "nudibranch", + } + path = GenerativeQuestionServiceClient.catalog_path(**expected) + + # Check that the path construction is reversible. + actual = GenerativeQuestionServiceClient.parse_catalog_path(path) + assert expected == actual + + +def test_common_billing_account_path(): + billing_account = "cuttlefish" + expected = "billingAccounts/{billing_account}".format( + billing_account=billing_account, + ) + actual = GenerativeQuestionServiceClient.common_billing_account_path( + billing_account + ) + assert expected == actual + + +def test_parse_common_billing_account_path(): + expected = { + "billing_account": "mussel", + } + path = GenerativeQuestionServiceClient.common_billing_account_path(**expected) + + # Check that the path construction is reversible. + actual = GenerativeQuestionServiceClient.parse_common_billing_account_path(path) + assert expected == actual + + +def test_common_folder_path(): + folder = "winkle" + expected = "folders/{folder}".format( + folder=folder, + ) + actual = GenerativeQuestionServiceClient.common_folder_path(folder) + assert expected == actual + + +def test_parse_common_folder_path(): + expected = { + "folder": "nautilus", + } + path = GenerativeQuestionServiceClient.common_folder_path(**expected) + + # Check that the path construction is reversible. + actual = GenerativeQuestionServiceClient.parse_common_folder_path(path) + assert expected == actual + + +def test_common_organization_path(): + organization = "scallop" + expected = "organizations/{organization}".format( + organization=organization, + ) + actual = GenerativeQuestionServiceClient.common_organization_path(organization) + assert expected == actual + + +def test_parse_common_organization_path(): + expected = { + "organization": "abalone", + } + path = GenerativeQuestionServiceClient.common_organization_path(**expected) + + # Check that the path construction is reversible. + actual = GenerativeQuestionServiceClient.parse_common_organization_path(path) + assert expected == actual + + +def test_common_project_path(): + project = "squid" + expected = "projects/{project}".format( + project=project, + ) + actual = GenerativeQuestionServiceClient.common_project_path(project) + assert expected == actual + + +def test_parse_common_project_path(): + expected = { + "project": "clam", + } + path = GenerativeQuestionServiceClient.common_project_path(**expected) + + # Check that the path construction is reversible. + actual = GenerativeQuestionServiceClient.parse_common_project_path(path) + assert expected == actual + + +def test_common_location_path(): + project = "whelk" + location = "octopus" + expected = "projects/{project}/locations/{location}".format( + project=project, + location=location, + ) + actual = GenerativeQuestionServiceClient.common_location_path(project, location) + assert expected == actual + + +def test_parse_common_location_path(): + expected = { + "project": "oyster", + "location": "nudibranch", + } + path = GenerativeQuestionServiceClient.common_location_path(**expected) + + # Check that the path construction is reversible. + actual = GenerativeQuestionServiceClient.parse_common_location_path(path) + assert expected == actual + + +def test_client_with_default_client_info(): + client_info = gapic_v1.client_info.ClientInfo() + + with mock.patch.object( + transports.GenerativeQuestionServiceTransport, "_prep_wrapped_messages" + ) as prep: + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + client_info=client_info, + ) + prep.assert_called_once_with(client_info) + + with mock.patch.object( + transports.GenerativeQuestionServiceTransport, "_prep_wrapped_messages" + ) as prep: + transport_class = GenerativeQuestionServiceClient.get_transport_class() + transport = transport_class( + credentials=ga_credentials.AnonymousCredentials(), + client_info=client_info, + ) + prep.assert_called_once_with(client_info) + + +@pytest.mark.asyncio +async def test_transport_close_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + with mock.patch.object( + type(getattr(client.transport, "grpc_channel")), "close" + ) as close: + async with client: + close.assert_not_called() + close.assert_called_once() + + +def test_get_operation_rest_bad_request( + transport: str = "rest", request_type=operations_pb2.GetOperationRequest +): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + request = request_type() + request = json_format.ParseDict( + { + "name": "projects/sample1/locations/sample2/catalogs/sample3/branches/sample4/operations/sample5" + }, + request, + ) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 400 + response_value.request = Request() + req.return_value = response_value + client.get_operation(request) + + +@pytest.mark.parametrize( + "request_type", + [ + operations_pb2.GetOperationRequest, + dict, + ], +) +def test_get_operation_rest(request_type): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request_init = { + "name": "projects/sample1/locations/sample2/catalogs/sample3/branches/sample4/operations/sample5" + } + request = request_type(**request_init) + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = operations_pb2.Operation() + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + response = client.get_operation(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, operations_pb2.Operation) + + +def test_list_operations_rest_bad_request( + transport: str = "rest", request_type=operations_pb2.ListOperationsRequest +): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + request = request_type() + request = json_format.ParseDict( + {"name": "projects/sample1/locations/sample2/catalogs/sample3"}, request + ) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 400 + response_value.request = Request() + req.return_value = response_value + client.list_operations(request) + + +@pytest.mark.parametrize( + "request_type", + [ + operations_pb2.ListOperationsRequest, + dict, + ], +) +def test_list_operations_rest(request_type): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request_init = {"name": "projects/sample1/locations/sample2/catalogs/sample3"} + request = request_type(**request_init) + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = operations_pb2.ListOperationsResponse() + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + response = client.list_operations(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, operations_pb2.ListOperationsResponse) + + +def test_get_operation(transport: str = "grpc"): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = operations_pb2.GetOperationRequest() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_operation), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.Operation() + response = client.get_operation(request) + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, operations_pb2.Operation) + + +@pytest.mark.asyncio +async def test_get_operation_async(transport: str = "grpc_asyncio"): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = operations_pb2.GetOperationRequest() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_operation), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation() + ) + response = await client.get_operation(request) + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, operations_pb2.Operation) + + +def test_get_operation_field_headers(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = operations_pb2.GetOperationRequest() + request.name = "locations" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_operation), "__call__") as call: + call.return_value = operations_pb2.Operation() + + client.get_operation(request) + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "name=locations", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_get_operation_field_headers_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = operations_pb2.GetOperationRequest() + request.name = "locations" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_operation), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation() + ) + await client.get_operation(request) + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "name=locations", + ) in kw["metadata"] + + +def test_get_operation_from_dict(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_operation), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.Operation() + + response = client.get_operation( + request={ + "name": "locations", + } + ) + call.assert_called() + + +@pytest.mark.asyncio +async def test_get_operation_from_dict_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_operation), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation() + ) + response = await client.get_operation( + request={ + "name": "locations", + } + ) + call.assert_called() + + +def test_list_operations(transport: str = "grpc"): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = operations_pb2.ListOperationsRequest() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_operations), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.ListOperationsResponse() + response = client.list_operations(request) + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, operations_pb2.ListOperationsResponse) + + +@pytest.mark.asyncio +async def test_list_operations_async(transport: str = "grpc_asyncio"): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = operations_pb2.ListOperationsRequest() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_operations), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.ListOperationsResponse() + ) + response = await client.list_operations(request) + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, operations_pb2.ListOperationsResponse) + + +def test_list_operations_field_headers(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = operations_pb2.ListOperationsRequest() + request.name = "locations" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_operations), "__call__") as call: + call.return_value = operations_pb2.ListOperationsResponse() + + client.list_operations(request) + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "name=locations", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_list_operations_field_headers_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = operations_pb2.ListOperationsRequest() + request.name = "locations" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_operations), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.ListOperationsResponse() + ) + await client.list_operations(request) + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "name=locations", + ) in kw["metadata"] + + +def test_list_operations_from_dict(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_operations), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.ListOperationsResponse() + + response = client.list_operations( + request={ + "name": "locations", + } + ) + call.assert_called() + + +@pytest.mark.asyncio +async def test_list_operations_from_dict_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_operations), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.ListOperationsResponse() + ) + response = await client.list_operations( + request={ + "name": "locations", + } + ) + call.assert_called() + + +def test_transport_close(): + transports = { + "rest": "_session", + "grpc": "_grpc_channel", + } + + for transport, close_name in transports.items(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + with mock.patch.object( + type(getattr(client.transport, close_name)), "close" + ) as close: + with client: + close.assert_not_called() + close.assert_called_once() + + +def test_client_ctx(): + transports = [ + "rest", + "grpc", + ] + for transport in transports: + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + # Test client calls underlying transport. + with mock.patch.object(type(client.transport), "close") as close: + close.assert_not_called() + with client: + pass + close.assert_called() + + +@pytest.mark.parametrize( + "client_class,transport_class", + [ + ( + GenerativeQuestionServiceClient, + transports.GenerativeQuestionServiceGrpcTransport, + ), + ( + GenerativeQuestionServiceAsyncClient, + transports.GenerativeQuestionServiceGrpcAsyncIOTransport, + ), + ], +) +def test_api_key_credentials(client_class, transport_class): + with mock.patch.object( + google.auth._default, "get_api_key_credentials", create=True + ) as get_api_key_credentials: + mock_cred = mock.Mock() + get_api_key_credentials.return_value = mock_cred + options = client_options.ClientOptions() + options.api_key = "api_key" + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options) + patched.assert_called_once_with( + credentials=mock_cred, + credentials_file=None, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) diff --git a/packages/google-cloud-retail/tests/unit/gapic/retail_v2alpha/test_model_service.py b/packages/google-cloud-retail/tests/unit/gapic/retail_v2alpha/test_model_service.py index aaae111e7abc..5877a15d3d71 100644 --- a/packages/google-cloud-retail/tests/unit/gapic/retail_v2alpha/test_model_service.py +++ b/packages/google-cloud-retail/tests/unit/gapic/retail_v2alpha/test_model_service.py @@ -4535,7 +4535,10 @@ def test_create_model_rest(request_type): } ], "model_features_config": { - "frequently_bought_together_config": {"context_products_type": 1} + "frequently_bought_together_config": {"context_products_type": 1}, + "llm_embedding_config": { + "llm_embedding_version": "llm_embedding_version_value" + }, }, } # The version of a generated dependency at test runtime may differ from the version used during generation. @@ -6620,7 +6623,10 @@ def test_update_model_rest(request_type): } ], "model_features_config": { - "frequently_bought_together_config": {"context_products_type": 1} + "frequently_bought_together_config": {"context_products_type": 1}, + "llm_embedding_config": { + "llm_embedding_version": "llm_embedding_version_value" + }, }, } # The version of a generated dependency at test runtime may differ from the version used during generation. diff --git a/packages/google-cloud-retail/tests/unit/gapic/retail_v2alpha/test_product_service.py b/packages/google-cloud-retail/tests/unit/gapic/retail_v2alpha/test_product_service.py index ce665974c733..b4393dedd311 100644 --- a/packages/google-cloud-retail/tests/unit/gapic/retail_v2alpha/test_product_service.py +++ b/packages/google-cloud-retail/tests/unit/gapic/retail_v2alpha/test_product_service.py @@ -65,8 +65,8 @@ pagers, transports, ) +from google.cloud.retail_v2alpha.types import common, export_config, import_config from google.cloud.retail_v2alpha.types import product_service, promotion, purge_config -from google.cloud.retail_v2alpha.types import common, import_config from google.cloud.retail_v2alpha.types import product from google.cloud.retail_v2alpha.types import product as gcr_product @@ -4011,6 +4011,293 @@ async def test_import_products_field_headers_async(): ) in kw["metadata"] +@pytest.mark.parametrize( + "request_type", + [ + export_config.ExportProductsRequest, + dict, + ], +) +def test_export_products(request_type, transport: str = "grpc"): + client = ProductServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.export_products), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.Operation(name="operations/spam") + response = client.export_products(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = export_config.ExportProductsRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, future.Future) + + +def test_export_products_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = ProductServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.export_products), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.export_products() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == export_config.ExportProductsRequest() + + +def test_export_products_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = ProductServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = export_config.ExportProductsRequest( + parent="parent_value", + filter="filter_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.export_products), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.export_products(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == export_config.ExportProductsRequest( + parent="parent_value", + filter="filter_value", + ) + + +def test_export_products_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = ProductServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.export_products in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.export_products] = mock_rpc + request = {} + client.export_products(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + # Operation methods call wrapper_fn to build a cached + # client._transport.operations_client instance on first rpc call. + # Subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + client.export_products(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_export_products_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = ProductServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.export_products), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/spam") + ) + response = await client.export_products() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == export_config.ExportProductsRequest() + + +@pytest.mark.asyncio +async def test_export_products_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = ProductServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.export_products + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.AsyncMock() + mock_rpc.return_value = mock.Mock() + client._client._transport._wrapped_methods[ + client._client._transport.export_products + ] = mock_rpc + + request = {} + await client.export_products(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + # Operation methods call wrapper_fn to build a cached + # client._transport.operations_client instance on first rpc call. + # Subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + await client.export_products(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_export_products_async( + transport: str = "grpc_asyncio", request_type=export_config.ExportProductsRequest +): + client = ProductServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.export_products), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/spam") + ) + response = await client.export_products(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = export_config.ExportProductsRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, future.Future) + + +@pytest.mark.asyncio +async def test_export_products_async_from_dict(): + await test_export_products_async(request_type=dict) + + +def test_export_products_field_headers(): + client = ProductServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = export_config.ExportProductsRequest() + + request.parent = "parent_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.export_products), "__call__") as call: + call.return_value = operations_pb2.Operation(name="operations/op") + client.export_products(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "parent=parent_value", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_export_products_field_headers_async(): + client = ProductServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = export_config.ExportProductsRequest() + + request.parent = "parent_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.export_products), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/op") + ) + await client.export_products(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "parent=parent_value", + ) in kw["metadata"] + + @pytest.mark.parametrize( "request_type", [ @@ -8527,6 +8814,263 @@ def test_import_products_rest_error(): ) +@pytest.mark.parametrize( + "request_type", + [ + export_config.ExportProductsRequest, + dict, + ], +) +def test_export_products_rest(request_type): + client = ProductServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = { + "parent": "projects/sample1/locations/sample2/catalogs/sample3/branches/sample4" + } + request = request_type(**request_init) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = operations_pb2.Operation(name="operations/spam") + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + response = client.export_products(request) + + # Establish that the response is the type that we expect. + assert response.operation.name == "operations/spam" + + +def test_export_products_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = ProductServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.export_products in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.export_products] = mock_rpc + + request = {} + client.export_products(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + # Operation methods build a cached wrapper on first rpc call + # subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + client.export_products(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_export_products_rest_required_fields( + request_type=export_config.ExportProductsRequest, +): + transport_class = transports.ProductServiceRestTransport + + request_init = {} + request_init["parent"] = "" + request = request_type(**request_init) + pb_request = request_type.pb(request) + jsonified_request = json.loads( + json_format.MessageToJson(pb_request, use_integers_for_enums=False) + ) + + # verify fields with default values are dropped + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).export_products._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + jsonified_request["parent"] = "parent_value" + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).export_products._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + assert "parent" in jsonified_request + assert jsonified_request["parent"] == "parent_value" + + client = ProductServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = operations_pb2.Operation(name="operations/spam") + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # We need to mock transcode() because providing default values + # for required fields will fail the real version if the http_options + # expect actual values for those fields. + with mock.patch.object(path_template, "transcode") as transcode: + # A uri without fields and an empty body will force all the + # request fields to show up in the query_params. + pb_request = request_type.pb(request) + transcode_result = { + "uri": "v1/sample_method", + "method": "post", + "query_params": pb_request, + } + transcode_result["body"] = pb_request + transcode.return_value = transcode_result + + response_value = Response() + response_value.status_code = 200 + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + response = client.export_products(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_export_products_rest_unset_required_fields(): + transport = transports.ProductServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.export_products._get_unset_required_fields({}) + assert set(unset_fields) == ( + set(()) + & set( + ( + "parent", + "outputConfig", + ) + ) + ) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_export_products_rest_interceptors(null_interceptor): + transport = transports.ProductServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.ProductServiceRestInterceptor(), + ) + client = ProductServiceClient(transport=transport) + with mock.patch.object( + type(client.transport._session), "request" + ) as req, mock.patch.object( + path_template, "transcode" + ) as transcode, mock.patch.object( + operation.Operation, "_set_result_from_operation" + ), mock.patch.object( + transports.ProductServiceRestInterceptor, "post_export_products" + ) as post, mock.patch.object( + transports.ProductServiceRestInterceptor, "pre_export_products" + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = export_config.ExportProductsRequest.pb( + export_config.ExportProductsRequest() + ) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = Response() + req.return_value.status_code = 200 + req.return_value.request = PreparedRequest() + req.return_value._content = json_format.MessageToJson( + operations_pb2.Operation() + ) + + request = export_config.ExportProductsRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = operations_pb2.Operation() + + client.export_products( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_export_products_rest_bad_request( + transport: str = "rest", request_type=export_config.ExportProductsRequest +): + client = ProductServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = { + "parent": "projects/sample1/locations/sample2/catalogs/sample3/branches/sample4" + } + request = request_type(**request_init) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 400 + response_value.request = Request() + req.return_value = response_value + client.export_products(request) + + +def test_export_products_rest_error(): + client = ProductServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + @pytest.mark.parametrize( "request_type", [ @@ -10280,6 +10824,7 @@ def test_product_service_base_transport(): "delete_product", "purge_products", "import_products", + "export_products", "set_inventory", "add_fulfillment_places", "remove_fulfillment_places", @@ -10588,6 +11133,9 @@ def test_product_service_client_transport_session_collision(transport_name): session1 = client1.transport.import_products._session session2 = client2.transport.import_products._session assert session1 != session2 + session1 = client1.transport.export_products._session + session2 = client2.transport.export_products._session + assert session1 != session2 session1 = client1.transport.set_inventory._session session2 = client2.transport.set_inventory._session assert session1 != session2 diff --git a/packages/google-cloud-retail/tests/unit/gapic/retail_v2alpha/test_user_event_service.py b/packages/google-cloud-retail/tests/unit/gapic/retail_v2alpha/test_user_event_service.py index 087c243f3357..097f321321e8 100644 --- a/packages/google-cloud-retail/tests/unit/gapic/retail_v2alpha/test_user_event_service.py +++ b/packages/google-cloud-retail/tests/unit/gapic/retail_v2alpha/test_user_event_service.py @@ -68,6 +68,7 @@ ) from google.cloud.retail_v2alpha.types import ( common, + export_config, import_config, product, promotion, @@ -2449,6 +2450,311 @@ async def test_import_user_events_field_headers_async(): ) in kw["metadata"] +@pytest.mark.parametrize( + "request_type", + [ + export_config.ExportUserEventsRequest, + dict, + ], +) +def test_export_user_events(request_type, transport: str = "grpc"): + client = UserEventServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.export_user_events), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.Operation(name="operations/spam") + response = client.export_user_events(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = export_config.ExportUserEventsRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, future.Future) + + +def test_export_user_events_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = UserEventServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.export_user_events), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.export_user_events() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == export_config.ExportUserEventsRequest() + + +def test_export_user_events_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = UserEventServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = export_config.ExportUserEventsRequest( + parent="parent_value", + filter="filter_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.export_user_events), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.export_user_events(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == export_config.ExportUserEventsRequest( + parent="parent_value", + filter="filter_value", + ) + + +def test_export_user_events_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = UserEventServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.export_user_events in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.export_user_events + ] = mock_rpc + request = {} + client.export_user_events(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + # Operation methods call wrapper_fn to build a cached + # client._transport.operations_client instance on first rpc call. + # Subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + client.export_user_events(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_export_user_events_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = UserEventServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.export_user_events), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/spam") + ) + response = await client.export_user_events() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == export_config.ExportUserEventsRequest() + + +@pytest.mark.asyncio +async def test_export_user_events_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = UserEventServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.export_user_events + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.AsyncMock() + mock_rpc.return_value = mock.Mock() + client._client._transport._wrapped_methods[ + client._client._transport.export_user_events + ] = mock_rpc + + request = {} + await client.export_user_events(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + # Operation methods call wrapper_fn to build a cached + # client._transport.operations_client instance on first rpc call. + # Subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + await client.export_user_events(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_export_user_events_async( + transport: str = "grpc_asyncio", request_type=export_config.ExportUserEventsRequest +): + client = UserEventServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.export_user_events), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/spam") + ) + response = await client.export_user_events(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = export_config.ExportUserEventsRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, future.Future) + + +@pytest.mark.asyncio +async def test_export_user_events_async_from_dict(): + await test_export_user_events_async(request_type=dict) + + +def test_export_user_events_field_headers(): + client = UserEventServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = export_config.ExportUserEventsRequest() + + request.parent = "parent_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.export_user_events), "__call__" + ) as call: + call.return_value = operations_pb2.Operation(name="operations/op") + client.export_user_events(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "parent=parent_value", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_export_user_events_field_headers_async(): + client = UserEventServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = export_config.ExportUserEventsRequest() + + request.parent = "parent_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.export_user_events), "__call__" + ) as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/op") + ) + await client.export_user_events(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "parent=parent_value", + ) in kw["metadata"] + + @pytest.mark.parametrize( "request_type", [ @@ -4031,6 +4337,263 @@ def test_import_user_events_rest_error(): ) +@pytest.mark.parametrize( + "request_type", + [ + export_config.ExportUserEventsRequest, + dict, + ], +) +def test_export_user_events_rest(request_type): + client = UserEventServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = {"parent": "projects/sample1/locations/sample2/catalogs/sample3"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = operations_pb2.Operation(name="operations/spam") + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + response = client.export_user_events(request) + + # Establish that the response is the type that we expect. + assert response.operation.name == "operations/spam" + + +def test_export_user_events_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = UserEventServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.export_user_events in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.export_user_events + ] = mock_rpc + + request = {} + client.export_user_events(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + # Operation methods build a cached wrapper on first rpc call + # subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + client.export_user_events(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_export_user_events_rest_required_fields( + request_type=export_config.ExportUserEventsRequest, +): + transport_class = transports.UserEventServiceRestTransport + + request_init = {} + request_init["parent"] = "" + request = request_type(**request_init) + pb_request = request_type.pb(request) + jsonified_request = json.loads( + json_format.MessageToJson(pb_request, use_integers_for_enums=False) + ) + + # verify fields with default values are dropped + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).export_user_events._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + jsonified_request["parent"] = "parent_value" + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).export_user_events._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + assert "parent" in jsonified_request + assert jsonified_request["parent"] == "parent_value" + + client = UserEventServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = operations_pb2.Operation(name="operations/spam") + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # We need to mock transcode() because providing default values + # for required fields will fail the real version if the http_options + # expect actual values for those fields. + with mock.patch.object(path_template, "transcode") as transcode: + # A uri without fields and an empty body will force all the + # request fields to show up in the query_params. + pb_request = request_type.pb(request) + transcode_result = { + "uri": "v1/sample_method", + "method": "post", + "query_params": pb_request, + } + transcode_result["body"] = pb_request + transcode.return_value = transcode_result + + response_value = Response() + response_value.status_code = 200 + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + response = client.export_user_events(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_export_user_events_rest_unset_required_fields(): + transport = transports.UserEventServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.export_user_events._get_unset_required_fields({}) + assert set(unset_fields) == ( + set(()) + & set( + ( + "parent", + "outputConfig", + ) + ) + ) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_export_user_events_rest_interceptors(null_interceptor): + transport = transports.UserEventServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.UserEventServiceRestInterceptor(), + ) + client = UserEventServiceClient(transport=transport) + with mock.patch.object( + type(client.transport._session), "request" + ) as req, mock.patch.object( + path_template, "transcode" + ) as transcode, mock.patch.object( + operation.Operation, "_set_result_from_operation" + ), mock.patch.object( + transports.UserEventServiceRestInterceptor, "post_export_user_events" + ) as post, mock.patch.object( + transports.UserEventServiceRestInterceptor, "pre_export_user_events" + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = export_config.ExportUserEventsRequest.pb( + export_config.ExportUserEventsRequest() + ) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = Response() + req.return_value.status_code = 200 + req.return_value.request = PreparedRequest() + req.return_value._content = json_format.MessageToJson( + operations_pb2.Operation() + ) + + request = export_config.ExportUserEventsRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = operations_pb2.Operation() + + client.export_user_events( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_export_user_events_rest_bad_request( + transport: str = "rest", request_type=export_config.ExportUserEventsRequest +): + client = UserEventServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = {"parent": "projects/sample1/locations/sample2/catalogs/sample3"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 400 + response_value.request = Request() + req.return_value = response_value + client.export_user_events(request) + + +def test_export_user_events_rest_error(): + client = UserEventServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + @pytest.mark.parametrize( "request_type", [ @@ -4423,6 +4986,7 @@ def test_user_event_service_base_transport(): "collect_user_event", "purge_user_events", "import_user_events", + "export_user_events", "rejoin_user_events", "get_operation", "list_operations", @@ -4718,6 +5282,9 @@ def test_user_event_service_client_transport_session_collision(transport_name): session1 = client1.transport.import_user_events._session session2 = client2.transport.import_user_events._session assert session1 != session2 + session1 = client1.transport.export_user_events._session + session2 = client2.transport.export_user_events._session + assert session1 != session2 session1 = client1.transport.rejoin_user_events._session session2 = client2.transport.rejoin_user_events._session assert session1 != session2 diff --git a/packages/google-cloud-retail/tests/unit/gapic/retail_v2beta/test_generative_question_service.py b/packages/google-cloud-retail/tests/unit/gapic/retail_v2beta/test_generative_question_service.py new file mode 100644 index 000000000000..7ff0edd787e2 --- /dev/null +++ b/packages/google-cloud-retail/tests/unit/gapic/retail_v2beta/test_generative_question_service.py @@ -0,0 +1,6449 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import os + +# try/except added for compatibility with python < 3.8 +try: + from unittest import mock + from unittest.mock import AsyncMock # pragma: NO COVER +except ImportError: # pragma: NO COVER + import mock + +from collections.abc import Iterable +import json +import math + +from google.api_core import gapic_v1, grpc_helpers, grpc_helpers_async, path_template +from google.api_core import api_core_version, client_options +from google.api_core import exceptions as core_exceptions +from google.api_core import retry as retries +import google.auth +from google.auth import credentials as ga_credentials +from google.auth.exceptions import MutualTLSChannelError +from google.cloud.location import locations_pb2 +from google.longrunning import operations_pb2 # type: ignore +from google.oauth2 import service_account +from google.protobuf import field_mask_pb2 # type: ignore +from google.protobuf import json_format +import grpc +from grpc.experimental import aio +from proto.marshal.rules import wrappers +from proto.marshal.rules.dates import DurationRule, TimestampRule +import pytest +from requests import PreparedRequest, Request, Response +from requests.sessions import Session + +from google.cloud.retail_v2beta.services.generative_question_service import ( + GenerativeQuestionServiceAsyncClient, + GenerativeQuestionServiceClient, + transports, +) +from google.cloud.retail_v2beta.types import ( + generative_question, + generative_question_service, +) + + +def client_cert_source_callback(): + return b"cert bytes", b"key bytes" + + +# If default endpoint is localhost, then default mtls endpoint will be the same. +# This method modifies the default endpoint so the client can produce a different +# mtls endpoint for endpoint testing purposes. +def modify_default_endpoint(client): + return ( + "foo.googleapis.com" + if ("localhost" in client.DEFAULT_ENDPOINT) + else client.DEFAULT_ENDPOINT + ) + + +# If default endpoint template is localhost, then default mtls endpoint will be the same. +# This method modifies the default endpoint template so the client can produce a different +# mtls endpoint for endpoint testing purposes. +def modify_default_endpoint_template(client): + return ( + "test.{UNIVERSE_DOMAIN}" + if ("localhost" in client._DEFAULT_ENDPOINT_TEMPLATE) + else client._DEFAULT_ENDPOINT_TEMPLATE + ) + + +def test__get_default_mtls_endpoint(): + api_endpoint = "example.googleapis.com" + api_mtls_endpoint = "example.mtls.googleapis.com" + sandbox_endpoint = "example.sandbox.googleapis.com" + sandbox_mtls_endpoint = "example.mtls.sandbox.googleapis.com" + non_googleapi = "api.example.com" + + assert GenerativeQuestionServiceClient._get_default_mtls_endpoint(None) is None + assert ( + GenerativeQuestionServiceClient._get_default_mtls_endpoint(api_endpoint) + == api_mtls_endpoint + ) + assert ( + GenerativeQuestionServiceClient._get_default_mtls_endpoint(api_mtls_endpoint) + == api_mtls_endpoint + ) + assert ( + GenerativeQuestionServiceClient._get_default_mtls_endpoint(sandbox_endpoint) + == sandbox_mtls_endpoint + ) + assert ( + GenerativeQuestionServiceClient._get_default_mtls_endpoint( + sandbox_mtls_endpoint + ) + == sandbox_mtls_endpoint + ) + assert ( + GenerativeQuestionServiceClient._get_default_mtls_endpoint(non_googleapi) + == non_googleapi + ) + + +def test__read_environment_variables(): + assert GenerativeQuestionServiceClient._read_environment_variables() == ( + False, + "auto", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "true"}): + assert GenerativeQuestionServiceClient._read_environment_variables() == ( + True, + "auto", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "false"}): + assert GenerativeQuestionServiceClient._read_environment_variables() == ( + False, + "auto", + None, + ) + + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"} + ): + with pytest.raises(ValueError) as excinfo: + GenerativeQuestionServiceClient._read_environment_variables() + assert ( + str(excinfo.value) + == "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): + assert GenerativeQuestionServiceClient._read_environment_variables() == ( + False, + "never", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): + assert GenerativeQuestionServiceClient._read_environment_variables() == ( + False, + "always", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "auto"}): + assert GenerativeQuestionServiceClient._read_environment_variables() == ( + False, + "auto", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "Unsupported"}): + with pytest.raises(MutualTLSChannelError) as excinfo: + GenerativeQuestionServiceClient._read_environment_variables() + assert ( + str(excinfo.value) + == "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`" + ) + + with mock.patch.dict(os.environ, {"GOOGLE_CLOUD_UNIVERSE_DOMAIN": "foo.com"}): + assert GenerativeQuestionServiceClient._read_environment_variables() == ( + False, + "auto", + "foo.com", + ) + + +def test__get_client_cert_source(): + mock_provided_cert_source = mock.Mock() + mock_default_cert_source = mock.Mock() + + assert GenerativeQuestionServiceClient._get_client_cert_source(None, False) is None + assert ( + GenerativeQuestionServiceClient._get_client_cert_source( + mock_provided_cert_source, False + ) + is None + ) + assert ( + GenerativeQuestionServiceClient._get_client_cert_source( + mock_provided_cert_source, True + ) + == mock_provided_cert_source + ) + + with mock.patch( + "google.auth.transport.mtls.has_default_client_cert_source", return_value=True + ): + with mock.patch( + "google.auth.transport.mtls.default_client_cert_source", + return_value=mock_default_cert_source, + ): + assert ( + GenerativeQuestionServiceClient._get_client_cert_source(None, True) + is mock_default_cert_source + ) + assert ( + GenerativeQuestionServiceClient._get_client_cert_source( + mock_provided_cert_source, "true" + ) + is mock_provided_cert_source + ) + + +@mock.patch.object( + GenerativeQuestionServiceClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(GenerativeQuestionServiceClient), +) +@mock.patch.object( + GenerativeQuestionServiceAsyncClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(GenerativeQuestionServiceAsyncClient), +) +def test__get_api_endpoint(): + api_override = "foo.com" + mock_client_cert_source = mock.Mock() + default_universe = GenerativeQuestionServiceClient._DEFAULT_UNIVERSE + default_endpoint = ( + GenerativeQuestionServiceClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=default_universe + ) + ) + mock_universe = "bar.com" + mock_endpoint = GenerativeQuestionServiceClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=mock_universe + ) + + assert ( + GenerativeQuestionServiceClient._get_api_endpoint( + api_override, mock_client_cert_source, default_universe, "always" + ) + == api_override + ) + assert ( + GenerativeQuestionServiceClient._get_api_endpoint( + None, mock_client_cert_source, default_universe, "auto" + ) + == GenerativeQuestionServiceClient.DEFAULT_MTLS_ENDPOINT + ) + assert ( + GenerativeQuestionServiceClient._get_api_endpoint( + None, None, default_universe, "auto" + ) + == default_endpoint + ) + assert ( + GenerativeQuestionServiceClient._get_api_endpoint( + None, None, default_universe, "always" + ) + == GenerativeQuestionServiceClient.DEFAULT_MTLS_ENDPOINT + ) + assert ( + GenerativeQuestionServiceClient._get_api_endpoint( + None, mock_client_cert_source, default_universe, "always" + ) + == GenerativeQuestionServiceClient.DEFAULT_MTLS_ENDPOINT + ) + assert ( + GenerativeQuestionServiceClient._get_api_endpoint( + None, None, mock_universe, "never" + ) + == mock_endpoint + ) + assert ( + GenerativeQuestionServiceClient._get_api_endpoint( + None, None, default_universe, "never" + ) + == default_endpoint + ) + + with pytest.raises(MutualTLSChannelError) as excinfo: + GenerativeQuestionServiceClient._get_api_endpoint( + None, mock_client_cert_source, mock_universe, "auto" + ) + assert ( + str(excinfo.value) + == "mTLS is not supported in any universe other than googleapis.com." + ) + + +def test__get_universe_domain(): + client_universe_domain = "foo.com" + universe_domain_env = "bar.com" + + assert ( + GenerativeQuestionServiceClient._get_universe_domain( + client_universe_domain, universe_domain_env + ) + == client_universe_domain + ) + assert ( + GenerativeQuestionServiceClient._get_universe_domain(None, universe_domain_env) + == universe_domain_env + ) + assert ( + GenerativeQuestionServiceClient._get_universe_domain(None, None) + == GenerativeQuestionServiceClient._DEFAULT_UNIVERSE + ) + + with pytest.raises(ValueError) as excinfo: + GenerativeQuestionServiceClient._get_universe_domain("", None) + assert str(excinfo.value) == "Universe Domain cannot be an empty string." + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name", + [ + ( + GenerativeQuestionServiceClient, + transports.GenerativeQuestionServiceGrpcTransport, + "grpc", + ), + ( + GenerativeQuestionServiceClient, + transports.GenerativeQuestionServiceRestTransport, + "rest", + ), + ], +) +def test__validate_universe_domain(client_class, transport_class, transport_name): + client = client_class( + transport=transport_class(credentials=ga_credentials.AnonymousCredentials()) + ) + assert client._validate_universe_domain() == True + + # Test the case when universe is already validated. + assert client._validate_universe_domain() == True + + if transport_name == "grpc": + # Test the case where credentials are provided by the + # `local_channel_credentials`. The default universes in both match. + channel = grpc.secure_channel( + "http://localhost/", grpc.local_channel_credentials() + ) + client = client_class(transport=transport_class(channel=channel)) + assert client._validate_universe_domain() == True + + # Test the case where credentials do not exist: e.g. a transport is provided + # with no credentials. Validation should still succeed because there is no + # mismatch with non-existent credentials. + channel = grpc.secure_channel( + "http://localhost/", grpc.local_channel_credentials() + ) + transport = transport_class(channel=channel) + transport._credentials = None + client = client_class(transport=transport) + assert client._validate_universe_domain() == True + + # TODO: This is needed to cater for older versions of google-auth + # Make this test unconditional once the minimum supported version of + # google-auth becomes 2.23.0 or higher. + google_auth_major, google_auth_minor = [ + int(part) for part in google.auth.__version__.split(".")[0:2] + ] + if google_auth_major > 2 or (google_auth_major == 2 and google_auth_minor >= 23): + credentials = ga_credentials.AnonymousCredentials() + credentials._universe_domain = "foo.com" + # Test the case when there is a universe mismatch from the credentials. + client = client_class(transport=transport_class(credentials=credentials)) + with pytest.raises(ValueError) as excinfo: + client._validate_universe_domain() + assert ( + str(excinfo.value) + == "The configured universe domain (googleapis.com) does not match the universe domain found in the credentials (foo.com). If you haven't configured the universe domain explicitly, `googleapis.com` is the default." + ) + + # Test the case when there is a universe mismatch from the client. + # + # TODO: Make this test unconditional once the minimum supported version of + # google-api-core becomes 2.15.0 or higher. + api_core_major, api_core_minor = [ + int(part) for part in api_core_version.__version__.split(".")[0:2] + ] + if api_core_major > 2 or (api_core_major == 2 and api_core_minor >= 15): + client = client_class( + client_options={"universe_domain": "bar.com"}, + transport=transport_class( + credentials=ga_credentials.AnonymousCredentials(), + ), + ) + with pytest.raises(ValueError) as excinfo: + client._validate_universe_domain() + assert ( + str(excinfo.value) + == "The configured universe domain (bar.com) does not match the universe domain found in the credentials (googleapis.com). If you haven't configured the universe domain explicitly, `googleapis.com` is the default." + ) + + # Test that ValueError is raised if universe_domain is provided via client options and credentials is None + with pytest.raises(ValueError): + client._compare_universes("foo.bar", None) + + +@pytest.mark.parametrize( + "client_class,transport_name", + [ + (GenerativeQuestionServiceClient, "grpc"), + (GenerativeQuestionServiceAsyncClient, "grpc_asyncio"), + (GenerativeQuestionServiceClient, "rest"), + ], +) +def test_generative_question_service_client_from_service_account_info( + client_class, transport_name +): + creds = ga_credentials.AnonymousCredentials() + with mock.patch.object( + service_account.Credentials, "from_service_account_info" + ) as factory: + factory.return_value = creds + info = {"valid": True} + client = client_class.from_service_account_info(info, transport=transport_name) + assert client.transport._credentials == creds + assert isinstance(client, client_class) + + assert client.transport._host == ( + "retail.googleapis.com:443" + if transport_name in ["grpc", "grpc_asyncio"] + else "https://retail.googleapis.com" + ) + + +@pytest.mark.parametrize( + "transport_class,transport_name", + [ + (transports.GenerativeQuestionServiceGrpcTransport, "grpc"), + (transports.GenerativeQuestionServiceGrpcAsyncIOTransport, "grpc_asyncio"), + (transports.GenerativeQuestionServiceRestTransport, "rest"), + ], +) +def test_generative_question_service_client_service_account_always_use_jwt( + transport_class, transport_name +): + with mock.patch.object( + service_account.Credentials, "with_always_use_jwt_access", create=True + ) as use_jwt: + creds = service_account.Credentials(None, None, None) + transport = transport_class(credentials=creds, always_use_jwt_access=True) + use_jwt.assert_called_once_with(True) + + with mock.patch.object( + service_account.Credentials, "with_always_use_jwt_access", create=True + ) as use_jwt: + creds = service_account.Credentials(None, None, None) + transport = transport_class(credentials=creds, always_use_jwt_access=False) + use_jwt.assert_not_called() + + +@pytest.mark.parametrize( + "client_class,transport_name", + [ + (GenerativeQuestionServiceClient, "grpc"), + (GenerativeQuestionServiceAsyncClient, "grpc_asyncio"), + (GenerativeQuestionServiceClient, "rest"), + ], +) +def test_generative_question_service_client_from_service_account_file( + client_class, transport_name +): + creds = ga_credentials.AnonymousCredentials() + with mock.patch.object( + service_account.Credentials, "from_service_account_file" + ) as factory: + factory.return_value = creds + client = client_class.from_service_account_file( + "dummy/file/path.json", transport=transport_name + ) + assert client.transport._credentials == creds + assert isinstance(client, client_class) + + client = client_class.from_service_account_json( + "dummy/file/path.json", transport=transport_name + ) + assert client.transport._credentials == creds + assert isinstance(client, client_class) + + assert client.transport._host == ( + "retail.googleapis.com:443" + if transport_name in ["grpc", "grpc_asyncio"] + else "https://retail.googleapis.com" + ) + + +def test_generative_question_service_client_get_transport_class(): + transport = GenerativeQuestionServiceClient.get_transport_class() + available_transports = [ + transports.GenerativeQuestionServiceGrpcTransport, + transports.GenerativeQuestionServiceRestTransport, + ] + assert transport in available_transports + + transport = GenerativeQuestionServiceClient.get_transport_class("grpc") + assert transport == transports.GenerativeQuestionServiceGrpcTransport + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name", + [ + ( + GenerativeQuestionServiceClient, + transports.GenerativeQuestionServiceGrpcTransport, + "grpc", + ), + ( + GenerativeQuestionServiceAsyncClient, + transports.GenerativeQuestionServiceGrpcAsyncIOTransport, + "grpc_asyncio", + ), + ( + GenerativeQuestionServiceClient, + transports.GenerativeQuestionServiceRestTransport, + "rest", + ), + ], +) +@mock.patch.object( + GenerativeQuestionServiceClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(GenerativeQuestionServiceClient), +) +@mock.patch.object( + GenerativeQuestionServiceAsyncClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(GenerativeQuestionServiceAsyncClient), +) +def test_generative_question_service_client_client_options( + client_class, transport_class, transport_name +): + # Check that if channel is provided we won't create a new one. + with mock.patch.object( + GenerativeQuestionServiceClient, "get_transport_class" + ) as gtc: + transport = transport_class(credentials=ga_credentials.AnonymousCredentials()) + client = client_class(transport=transport) + gtc.assert_not_called() + + # Check that if channel is provided via str we will create a new one. + with mock.patch.object( + GenerativeQuestionServiceClient, "get_transport_class" + ) as gtc: + client = client_class(transport=transport_name) + gtc.assert_called() + + # Check the case api_endpoint is provided. + options = client_options.ClientOptions(api_endpoint="squid.clam.whelk") + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(transport=transport_name, client_options=options) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host="squid.clam.whelk", + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT is + # "never". + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT is + # "always". + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client.DEFAULT_MTLS_ENDPOINT, + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT has + # unsupported value. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "Unsupported"}): + with pytest.raises(MutualTLSChannelError) as excinfo: + client = client_class(transport=transport_name) + assert ( + str(excinfo.value) + == "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`" + ) + + # Check the case GOOGLE_API_USE_CLIENT_CERTIFICATE has unsupported value. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"} + ): + with pytest.raises(ValueError) as excinfo: + client = client_class(transport=transport_name) + assert ( + str(excinfo.value) + == "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + + # Check the case quota_project_id is provided + options = client_options.ClientOptions(quota_project_id="octopus") + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options, transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id="octopus", + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + # Check the case api_endpoint is provided + options = client_options.ClientOptions( + api_audience="https://language.googleapis.com" + ) + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options, transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience="https://language.googleapis.com", + ) + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name,use_client_cert_env", + [ + ( + GenerativeQuestionServiceClient, + transports.GenerativeQuestionServiceGrpcTransport, + "grpc", + "true", + ), + ( + GenerativeQuestionServiceAsyncClient, + transports.GenerativeQuestionServiceGrpcAsyncIOTransport, + "grpc_asyncio", + "true", + ), + ( + GenerativeQuestionServiceClient, + transports.GenerativeQuestionServiceGrpcTransport, + "grpc", + "false", + ), + ( + GenerativeQuestionServiceAsyncClient, + transports.GenerativeQuestionServiceGrpcAsyncIOTransport, + "grpc_asyncio", + "false", + ), + ( + GenerativeQuestionServiceClient, + transports.GenerativeQuestionServiceRestTransport, + "rest", + "true", + ), + ( + GenerativeQuestionServiceClient, + transports.GenerativeQuestionServiceRestTransport, + "rest", + "false", + ), + ], +) +@mock.patch.object( + GenerativeQuestionServiceClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(GenerativeQuestionServiceClient), +) +@mock.patch.object( + GenerativeQuestionServiceAsyncClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(GenerativeQuestionServiceAsyncClient), +) +@mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "auto"}) +def test_generative_question_service_client_mtls_env_auto( + client_class, transport_class, transport_name, use_client_cert_env +): + # This tests the endpoint autoswitch behavior. Endpoint is autoswitched to the default + # mtls endpoint, if GOOGLE_API_USE_CLIENT_CERTIFICATE is "true" and client cert exists. + + # Check the case client_cert_source is provided. Whether client cert is used depends on + # GOOGLE_API_USE_CLIENT_CERTIFICATE value. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": use_client_cert_env} + ): + options = client_options.ClientOptions( + client_cert_source=client_cert_source_callback + ) + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options, transport=transport_name) + + if use_client_cert_env == "false": + expected_client_cert_source = None + expected_host = client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ) + else: + expected_client_cert_source = client_cert_source_callback + expected_host = client.DEFAULT_MTLS_ENDPOINT + + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=expected_host, + scopes=None, + client_cert_source_for_mtls=expected_client_cert_source, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + # Check the case ADC client cert is provided. Whether client cert is used depends on + # GOOGLE_API_USE_CLIENT_CERTIFICATE value. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": use_client_cert_env} + ): + with mock.patch.object(transport_class, "__init__") as patched: + with mock.patch( + "google.auth.transport.mtls.has_default_client_cert_source", + return_value=True, + ): + with mock.patch( + "google.auth.transport.mtls.default_client_cert_source", + return_value=client_cert_source_callback, + ): + if use_client_cert_env == "false": + expected_host = client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ) + expected_client_cert_source = None + else: + expected_host = client.DEFAULT_MTLS_ENDPOINT + expected_client_cert_source = client_cert_source_callback + + patched.return_value = None + client = client_class(transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=expected_host, + scopes=None, + client_cert_source_for_mtls=expected_client_cert_source, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + # Check the case client_cert_source and ADC client cert are not provided. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": use_client_cert_env} + ): + with mock.patch.object(transport_class, "__init__") as patched: + with mock.patch( + "google.auth.transport.mtls.has_default_client_cert_source", + return_value=False, + ): + patched.return_value = None + client = client_class(transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + +@pytest.mark.parametrize( + "client_class", + [GenerativeQuestionServiceClient, GenerativeQuestionServiceAsyncClient], +) +@mock.patch.object( + GenerativeQuestionServiceClient, + "DEFAULT_ENDPOINT", + modify_default_endpoint(GenerativeQuestionServiceClient), +) +@mock.patch.object( + GenerativeQuestionServiceAsyncClient, + "DEFAULT_ENDPOINT", + modify_default_endpoint(GenerativeQuestionServiceAsyncClient), +) +def test_generative_question_service_client_get_mtls_endpoint_and_cert_source( + client_class, +): + mock_client_cert_source = mock.Mock() + + # Test the case GOOGLE_API_USE_CLIENT_CERTIFICATE is "true". + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "true"}): + mock_api_endpoint = "foo" + options = client_options.ClientOptions( + client_cert_source=mock_client_cert_source, api_endpoint=mock_api_endpoint + ) + api_endpoint, cert_source = client_class.get_mtls_endpoint_and_cert_source( + options + ) + assert api_endpoint == mock_api_endpoint + assert cert_source == mock_client_cert_source + + # Test the case GOOGLE_API_USE_CLIENT_CERTIFICATE is "false". + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "false"}): + mock_client_cert_source = mock.Mock() + mock_api_endpoint = "foo" + options = client_options.ClientOptions( + client_cert_source=mock_client_cert_source, api_endpoint=mock_api_endpoint + ) + api_endpoint, cert_source = client_class.get_mtls_endpoint_and_cert_source( + options + ) + assert api_endpoint == mock_api_endpoint + assert cert_source is None + + # Test the case GOOGLE_API_USE_MTLS_ENDPOINT is "never". + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): + api_endpoint, cert_source = client_class.get_mtls_endpoint_and_cert_source() + assert api_endpoint == client_class.DEFAULT_ENDPOINT + assert cert_source is None + + # Test the case GOOGLE_API_USE_MTLS_ENDPOINT is "always". + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): + api_endpoint, cert_source = client_class.get_mtls_endpoint_and_cert_source() + assert api_endpoint == client_class.DEFAULT_MTLS_ENDPOINT + assert cert_source is None + + # Test the case GOOGLE_API_USE_MTLS_ENDPOINT is "auto" and default cert doesn't exist. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "true"}): + with mock.patch( + "google.auth.transport.mtls.has_default_client_cert_source", + return_value=False, + ): + api_endpoint, cert_source = client_class.get_mtls_endpoint_and_cert_source() + assert api_endpoint == client_class.DEFAULT_ENDPOINT + assert cert_source is None + + # Test the case GOOGLE_API_USE_MTLS_ENDPOINT is "auto" and default cert exists. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "true"}): + with mock.patch( + "google.auth.transport.mtls.has_default_client_cert_source", + return_value=True, + ): + with mock.patch( + "google.auth.transport.mtls.default_client_cert_source", + return_value=mock_client_cert_source, + ): + ( + api_endpoint, + cert_source, + ) = client_class.get_mtls_endpoint_and_cert_source() + assert api_endpoint == client_class.DEFAULT_MTLS_ENDPOINT + assert cert_source == mock_client_cert_source + + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT has + # unsupported value. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "Unsupported"}): + with pytest.raises(MutualTLSChannelError) as excinfo: + client_class.get_mtls_endpoint_and_cert_source() + + assert ( + str(excinfo.value) + == "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`" + ) + + # Check the case GOOGLE_API_USE_CLIENT_CERTIFICATE has unsupported value. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"} + ): + with pytest.raises(ValueError) as excinfo: + client_class.get_mtls_endpoint_and_cert_source() + + assert ( + str(excinfo.value) + == "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + + +@pytest.mark.parametrize( + "client_class", + [GenerativeQuestionServiceClient, GenerativeQuestionServiceAsyncClient], +) +@mock.patch.object( + GenerativeQuestionServiceClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(GenerativeQuestionServiceClient), +) +@mock.patch.object( + GenerativeQuestionServiceAsyncClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(GenerativeQuestionServiceAsyncClient), +) +def test_generative_question_service_client_client_api_endpoint(client_class): + mock_client_cert_source = client_cert_source_callback + api_override = "foo.com" + default_universe = GenerativeQuestionServiceClient._DEFAULT_UNIVERSE + default_endpoint = ( + GenerativeQuestionServiceClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=default_universe + ) + ) + mock_universe = "bar.com" + mock_endpoint = GenerativeQuestionServiceClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=mock_universe + ) + + # If ClientOptions.api_endpoint is set and GOOGLE_API_USE_CLIENT_CERTIFICATE="true", + # use ClientOptions.api_endpoint as the api endpoint regardless. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "true"}): + with mock.patch( + "google.auth.transport.requests.AuthorizedSession.configure_mtls_channel" + ): + options = client_options.ClientOptions( + client_cert_source=mock_client_cert_source, api_endpoint=api_override + ) + client = client_class( + client_options=options, + credentials=ga_credentials.AnonymousCredentials(), + ) + assert client.api_endpoint == api_override + + # If ClientOptions.api_endpoint is not set and GOOGLE_API_USE_MTLS_ENDPOINT="never", + # use the _DEFAULT_ENDPOINT_TEMPLATE populated with GDU as the api endpoint. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): + client = client_class(credentials=ga_credentials.AnonymousCredentials()) + assert client.api_endpoint == default_endpoint + + # If ClientOptions.api_endpoint is not set and GOOGLE_API_USE_MTLS_ENDPOINT="always", + # use the DEFAULT_MTLS_ENDPOINT as the api endpoint. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): + client = client_class(credentials=ga_credentials.AnonymousCredentials()) + assert client.api_endpoint == client_class.DEFAULT_MTLS_ENDPOINT + + # If ClientOptions.api_endpoint is not set, GOOGLE_API_USE_MTLS_ENDPOINT="auto" (default), + # GOOGLE_API_USE_CLIENT_CERTIFICATE="false" (default), default cert source doesn't exist, + # and ClientOptions.universe_domain="bar.com", + # use the _DEFAULT_ENDPOINT_TEMPLATE populated with universe domain as the api endpoint. + options = client_options.ClientOptions() + universe_exists = hasattr(options, "universe_domain") + if universe_exists: + options = client_options.ClientOptions(universe_domain=mock_universe) + client = client_class( + client_options=options, credentials=ga_credentials.AnonymousCredentials() + ) + else: + client = client_class( + client_options=options, credentials=ga_credentials.AnonymousCredentials() + ) + assert client.api_endpoint == ( + mock_endpoint if universe_exists else default_endpoint + ) + assert client.universe_domain == ( + mock_universe if universe_exists else default_universe + ) + + # If ClientOptions does not have a universe domain attribute and GOOGLE_API_USE_MTLS_ENDPOINT="never", + # use the _DEFAULT_ENDPOINT_TEMPLATE populated with GDU as the api endpoint. + options = client_options.ClientOptions() + if hasattr(options, "universe_domain"): + delattr(options, "universe_domain") + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): + client = client_class( + client_options=options, credentials=ga_credentials.AnonymousCredentials() + ) + assert client.api_endpoint == default_endpoint + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name", + [ + ( + GenerativeQuestionServiceClient, + transports.GenerativeQuestionServiceGrpcTransport, + "grpc", + ), + ( + GenerativeQuestionServiceAsyncClient, + transports.GenerativeQuestionServiceGrpcAsyncIOTransport, + "grpc_asyncio", + ), + ( + GenerativeQuestionServiceClient, + transports.GenerativeQuestionServiceRestTransport, + "rest", + ), + ], +) +def test_generative_question_service_client_client_options_scopes( + client_class, transport_class, transport_name +): + # Check the case scopes are provided. + options = client_options.ClientOptions( + scopes=["1", "2"], + ) + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options, transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), + scopes=["1", "2"], + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name,grpc_helpers", + [ + ( + GenerativeQuestionServiceClient, + transports.GenerativeQuestionServiceGrpcTransport, + "grpc", + grpc_helpers, + ), + ( + GenerativeQuestionServiceAsyncClient, + transports.GenerativeQuestionServiceGrpcAsyncIOTransport, + "grpc_asyncio", + grpc_helpers_async, + ), + ( + GenerativeQuestionServiceClient, + transports.GenerativeQuestionServiceRestTransport, + "rest", + None, + ), + ], +) +def test_generative_question_service_client_client_options_credentials_file( + client_class, transport_class, transport_name, grpc_helpers +): + # Check the case credentials file is provided. + options = client_options.ClientOptions(credentials_file="credentials.json") + + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options, transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file="credentials.json", + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + +def test_generative_question_service_client_client_options_from_dict(): + with mock.patch( + "google.cloud.retail_v2beta.services.generative_question_service.transports.GenerativeQuestionServiceGrpcTransport.__init__" + ) as grpc_transport: + grpc_transport.return_value = None + client = GenerativeQuestionServiceClient( + client_options={"api_endpoint": "squid.clam.whelk"} + ) + grpc_transport.assert_called_once_with( + credentials=None, + credentials_file=None, + host="squid.clam.whelk", + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name,grpc_helpers", + [ + ( + GenerativeQuestionServiceClient, + transports.GenerativeQuestionServiceGrpcTransport, + "grpc", + grpc_helpers, + ), + ( + GenerativeQuestionServiceAsyncClient, + transports.GenerativeQuestionServiceGrpcAsyncIOTransport, + "grpc_asyncio", + grpc_helpers_async, + ), + ], +) +def test_generative_question_service_client_create_channel_credentials_file( + client_class, transport_class, transport_name, grpc_helpers +): + # Check the case credentials file is provided. + options = client_options.ClientOptions(credentials_file="credentials.json") + + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options, transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file="credentials.json", + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + # test that the credentials from file are saved and used as the credentials. + with mock.patch.object( + google.auth, "load_credentials_from_file", autospec=True + ) as load_creds, mock.patch.object( + google.auth, "default", autospec=True + ) as adc, mock.patch.object( + grpc_helpers, "create_channel" + ) as create_channel: + creds = ga_credentials.AnonymousCredentials() + file_creds = ga_credentials.AnonymousCredentials() + load_creds.return_value = (file_creds, None) + adc.return_value = (creds, None) + client = client_class(client_options=options, transport=transport_name) + create_channel.assert_called_with( + "retail.googleapis.com:443", + credentials=file_creds, + credentials_file=None, + quota_project_id=None, + default_scopes=("https://www.googleapis.com/auth/cloud-platform",), + scopes=None, + default_host="retail.googleapis.com", + ssl_credentials=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + +@pytest.mark.parametrize( + "request_type", + [ + generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest, + dict, + ], +) +def test_update_generative_questions_feature_config( + request_type, transport: str = "grpc" +): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_questions_feature_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = generative_question.GenerativeQuestionsFeatureConfig( + catalog="catalog_value", + feature_enabled=True, + minimum_products=1743, + ) + response = client.update_generative_questions_feature_config(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = ( + generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest() + ) + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, generative_question.GenerativeQuestionsFeatureConfig) + assert response.catalog == "catalog_value" + assert response.feature_enabled is True + assert response.minimum_products == 1743 + + +def test_update_generative_questions_feature_config_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_questions_feature_config), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.update_generative_questions_feature_config() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert ( + args[0] + == generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest() + ) + + +def test_update_generative_questions_feature_config_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = ( + generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest() + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_questions_feature_config), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.update_generative_questions_feature_config(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert ( + args[0] + == generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest() + ) + + +def test_update_generative_questions_feature_config_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.update_generative_questions_feature_config + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.update_generative_questions_feature_config + ] = mock_rpc + request = {} + client.update_generative_questions_feature_config(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.update_generative_questions_feature_config(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_update_generative_questions_feature_config_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_questions_feature_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question.GenerativeQuestionsFeatureConfig( + catalog="catalog_value", + feature_enabled=True, + minimum_products=1743, + ) + ) + response = await client.update_generative_questions_feature_config() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert ( + args[0] + == generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest() + ) + + +@pytest.mark.asyncio +async def test_update_generative_questions_feature_config_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.update_generative_questions_feature_config + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.AsyncMock() + mock_rpc.return_value = mock.Mock() + client._client._transport._wrapped_methods[ + client._client._transport.update_generative_questions_feature_config + ] = mock_rpc + + request = {} + await client.update_generative_questions_feature_config(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + await client.update_generative_questions_feature_config(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_update_generative_questions_feature_config_async( + transport: str = "grpc_asyncio", + request_type=generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest, +): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_questions_feature_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question.GenerativeQuestionsFeatureConfig( + catalog="catalog_value", + feature_enabled=True, + minimum_products=1743, + ) + ) + response = await client.update_generative_questions_feature_config(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = ( + generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest() + ) + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, generative_question.GenerativeQuestionsFeatureConfig) + assert response.catalog == "catalog_value" + assert response.feature_enabled is True + assert response.minimum_products == 1743 + + +@pytest.mark.asyncio +async def test_update_generative_questions_feature_config_async_from_dict(): + await test_update_generative_questions_feature_config_async(request_type=dict) + + +def test_update_generative_questions_feature_config_field_headers(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = ( + generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest() + ) + + request.generative_questions_feature_config.catalog = "catalog_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_questions_feature_config), "__call__" + ) as call: + call.return_value = generative_question.GenerativeQuestionsFeatureConfig() + client.update_generative_questions_feature_config(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "generative_questions_feature_config.catalog=catalog_value", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_update_generative_questions_feature_config_field_headers_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = ( + generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest() + ) + + request.generative_questions_feature_config.catalog = "catalog_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_questions_feature_config), "__call__" + ) as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question.GenerativeQuestionsFeatureConfig() + ) + await client.update_generative_questions_feature_config(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "generative_questions_feature_config.catalog=catalog_value", + ) in kw["metadata"] + + +def test_update_generative_questions_feature_config_flattened(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_questions_feature_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = generative_question.GenerativeQuestionsFeatureConfig() + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.update_generative_questions_feature_config( + generative_questions_feature_config=generative_question.GenerativeQuestionsFeatureConfig( + catalog="catalog_value" + ), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + arg = args[0].generative_questions_feature_config + mock_val = generative_question.GenerativeQuestionsFeatureConfig( + catalog="catalog_value" + ) + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val + + +def test_update_generative_questions_feature_config_flattened_error(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.update_generative_questions_feature_config( + generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest(), + generative_questions_feature_config=generative_question.GenerativeQuestionsFeatureConfig( + catalog="catalog_value" + ), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + +@pytest.mark.asyncio +async def test_update_generative_questions_feature_config_flattened_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_questions_feature_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = generative_question.GenerativeQuestionsFeatureConfig() + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question.GenerativeQuestionsFeatureConfig() + ) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.update_generative_questions_feature_config( + generative_questions_feature_config=generative_question.GenerativeQuestionsFeatureConfig( + catalog="catalog_value" + ), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + arg = args[0].generative_questions_feature_config + mock_val = generative_question.GenerativeQuestionsFeatureConfig( + catalog="catalog_value" + ) + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val + + +@pytest.mark.asyncio +async def test_update_generative_questions_feature_config_flattened_error_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + await client.update_generative_questions_feature_config( + generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest(), + generative_questions_feature_config=generative_question.GenerativeQuestionsFeatureConfig( + catalog="catalog_value" + ), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + +@pytest.mark.parametrize( + "request_type", + [ + generative_question_service.GetGenerativeQuestionsFeatureConfigRequest, + dict, + ], +) +def test_get_generative_questions_feature_config(request_type, transport: str = "grpc"): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.get_generative_questions_feature_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = generative_question.GenerativeQuestionsFeatureConfig( + catalog="catalog_value", + feature_enabled=True, + minimum_products=1743, + ) + response = client.get_generative_questions_feature_config(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = ( + generative_question_service.GetGenerativeQuestionsFeatureConfigRequest() + ) + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, generative_question.GenerativeQuestionsFeatureConfig) + assert response.catalog == "catalog_value" + assert response.feature_enabled is True + assert response.minimum_products == 1743 + + +def test_get_generative_questions_feature_config_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.get_generative_questions_feature_config), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.get_generative_questions_feature_config() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert ( + args[0] + == generative_question_service.GetGenerativeQuestionsFeatureConfigRequest() + ) + + +def test_get_generative_questions_feature_config_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = generative_question_service.GetGenerativeQuestionsFeatureConfigRequest( + catalog="catalog_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.get_generative_questions_feature_config), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.get_generative_questions_feature_config(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[ + 0 + ] == generative_question_service.GetGenerativeQuestionsFeatureConfigRequest( + catalog="catalog_value", + ) + + +def test_get_generative_questions_feature_config_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.get_generative_questions_feature_config + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.get_generative_questions_feature_config + ] = mock_rpc + request = {} + client.get_generative_questions_feature_config(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.get_generative_questions_feature_config(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_get_generative_questions_feature_config_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.get_generative_questions_feature_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question.GenerativeQuestionsFeatureConfig( + catalog="catalog_value", + feature_enabled=True, + minimum_products=1743, + ) + ) + response = await client.get_generative_questions_feature_config() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert ( + args[0] + == generative_question_service.GetGenerativeQuestionsFeatureConfigRequest() + ) + + +@pytest.mark.asyncio +async def test_get_generative_questions_feature_config_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.get_generative_questions_feature_config + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.AsyncMock() + mock_rpc.return_value = mock.Mock() + client._client._transport._wrapped_methods[ + client._client._transport.get_generative_questions_feature_config + ] = mock_rpc + + request = {} + await client.get_generative_questions_feature_config(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + await client.get_generative_questions_feature_config(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_get_generative_questions_feature_config_async( + transport: str = "grpc_asyncio", + request_type=generative_question_service.GetGenerativeQuestionsFeatureConfigRequest, +): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.get_generative_questions_feature_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question.GenerativeQuestionsFeatureConfig( + catalog="catalog_value", + feature_enabled=True, + minimum_products=1743, + ) + ) + response = await client.get_generative_questions_feature_config(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = ( + generative_question_service.GetGenerativeQuestionsFeatureConfigRequest() + ) + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, generative_question.GenerativeQuestionsFeatureConfig) + assert response.catalog == "catalog_value" + assert response.feature_enabled is True + assert response.minimum_products == 1743 + + +@pytest.mark.asyncio +async def test_get_generative_questions_feature_config_async_from_dict(): + await test_get_generative_questions_feature_config_async(request_type=dict) + + +def test_get_generative_questions_feature_config_field_headers(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = generative_question_service.GetGenerativeQuestionsFeatureConfigRequest() + + request.catalog = "catalog_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.get_generative_questions_feature_config), "__call__" + ) as call: + call.return_value = generative_question.GenerativeQuestionsFeatureConfig() + client.get_generative_questions_feature_config(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "catalog=catalog_value", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_get_generative_questions_feature_config_field_headers_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = generative_question_service.GetGenerativeQuestionsFeatureConfigRequest() + + request.catalog = "catalog_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.get_generative_questions_feature_config), "__call__" + ) as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question.GenerativeQuestionsFeatureConfig() + ) + await client.get_generative_questions_feature_config(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "catalog=catalog_value", + ) in kw["metadata"] + + +def test_get_generative_questions_feature_config_flattened(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.get_generative_questions_feature_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = generative_question.GenerativeQuestionsFeatureConfig() + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.get_generative_questions_feature_config( + catalog="catalog_value", + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + arg = args[0].catalog + mock_val = "catalog_value" + assert arg == mock_val + + +def test_get_generative_questions_feature_config_flattened_error(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.get_generative_questions_feature_config( + generative_question_service.GetGenerativeQuestionsFeatureConfigRequest(), + catalog="catalog_value", + ) + + +@pytest.mark.asyncio +async def test_get_generative_questions_feature_config_flattened_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.get_generative_questions_feature_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = generative_question.GenerativeQuestionsFeatureConfig() + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question.GenerativeQuestionsFeatureConfig() + ) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.get_generative_questions_feature_config( + catalog="catalog_value", + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + arg = args[0].catalog + mock_val = "catalog_value" + assert arg == mock_val + + +@pytest.mark.asyncio +async def test_get_generative_questions_feature_config_flattened_error_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + await client.get_generative_questions_feature_config( + generative_question_service.GetGenerativeQuestionsFeatureConfigRequest(), + catalog="catalog_value", + ) + + +@pytest.mark.parametrize( + "request_type", + [ + generative_question_service.ListGenerativeQuestionConfigsRequest, + dict, + ], +) +def test_list_generative_question_configs(request_type, transport: str = "grpc"): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_generative_question_configs), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = ( + generative_question_service.ListGenerativeQuestionConfigsResponse() + ) + response = client.list_generative_question_configs(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = generative_question_service.ListGenerativeQuestionConfigsRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance( + response, generative_question_service.ListGenerativeQuestionConfigsResponse + ) + + +def test_list_generative_question_configs_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_generative_question_configs), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.list_generative_question_configs() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert ( + args[0] + == generative_question_service.ListGenerativeQuestionConfigsRequest() + ) + + +def test_list_generative_question_configs_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = generative_question_service.ListGenerativeQuestionConfigsRequest( + parent="parent_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_generative_question_configs), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.list_generative_question_configs(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[ + 0 + ] == generative_question_service.ListGenerativeQuestionConfigsRequest( + parent="parent_value", + ) + + +def test_list_generative_question_configs_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.list_generative_question_configs + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.list_generative_question_configs + ] = mock_rpc + request = {} + client.list_generative_question_configs(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.list_generative_question_configs(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_list_generative_question_configs_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_generative_question_configs), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question_service.ListGenerativeQuestionConfigsResponse() + ) + response = await client.list_generative_question_configs() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert ( + args[0] + == generative_question_service.ListGenerativeQuestionConfigsRequest() + ) + + +@pytest.mark.asyncio +async def test_list_generative_question_configs_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.list_generative_question_configs + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.AsyncMock() + mock_rpc.return_value = mock.Mock() + client._client._transport._wrapped_methods[ + client._client._transport.list_generative_question_configs + ] = mock_rpc + + request = {} + await client.list_generative_question_configs(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + await client.list_generative_question_configs(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_list_generative_question_configs_async( + transport: str = "grpc_asyncio", + request_type=generative_question_service.ListGenerativeQuestionConfigsRequest, +): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_generative_question_configs), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question_service.ListGenerativeQuestionConfigsResponse() + ) + response = await client.list_generative_question_configs(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = generative_question_service.ListGenerativeQuestionConfigsRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance( + response, generative_question_service.ListGenerativeQuestionConfigsResponse + ) + + +@pytest.mark.asyncio +async def test_list_generative_question_configs_async_from_dict(): + await test_list_generative_question_configs_async(request_type=dict) + + +def test_list_generative_question_configs_field_headers(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = generative_question_service.ListGenerativeQuestionConfigsRequest() + + request.parent = "parent_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_generative_question_configs), "__call__" + ) as call: + call.return_value = ( + generative_question_service.ListGenerativeQuestionConfigsResponse() + ) + client.list_generative_question_configs(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "parent=parent_value", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_list_generative_question_configs_field_headers_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = generative_question_service.ListGenerativeQuestionConfigsRequest() + + request.parent = "parent_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_generative_question_configs), "__call__" + ) as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question_service.ListGenerativeQuestionConfigsResponse() + ) + await client.list_generative_question_configs(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "parent=parent_value", + ) in kw["metadata"] + + +def test_list_generative_question_configs_flattened(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_generative_question_configs), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = ( + generative_question_service.ListGenerativeQuestionConfigsResponse() + ) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.list_generative_question_configs( + parent="parent_value", + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + + +def test_list_generative_question_configs_flattened_error(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.list_generative_question_configs( + generative_question_service.ListGenerativeQuestionConfigsRequest(), + parent="parent_value", + ) + + +@pytest.mark.asyncio +async def test_list_generative_question_configs_flattened_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_generative_question_configs), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = ( + generative_question_service.ListGenerativeQuestionConfigsResponse() + ) + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question_service.ListGenerativeQuestionConfigsResponse() + ) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.list_generative_question_configs( + parent="parent_value", + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + + +@pytest.mark.asyncio +async def test_list_generative_question_configs_flattened_error_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + await client.list_generative_question_configs( + generative_question_service.ListGenerativeQuestionConfigsRequest(), + parent="parent_value", + ) + + +@pytest.mark.parametrize( + "request_type", + [ + generative_question_service.UpdateGenerativeQuestionConfigRequest, + dict, + ], +) +def test_update_generative_question_config(request_type, transport: str = "grpc"): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_question_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = generative_question.GenerativeQuestionConfig( + catalog="catalog_value", + facet="facet_value", + generated_question="generated_question_value", + final_question="final_question_value", + example_values=["example_values_value"], + frequency=0.978, + allowed_in_conversation=True, + ) + response = client.update_generative_question_config(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = generative_question_service.UpdateGenerativeQuestionConfigRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, generative_question.GenerativeQuestionConfig) + assert response.catalog == "catalog_value" + assert response.facet == "facet_value" + assert response.generated_question == "generated_question_value" + assert response.final_question == "final_question_value" + assert response.example_values == ["example_values_value"] + assert math.isclose(response.frequency, 0.978, rel_tol=1e-6) + assert response.allowed_in_conversation is True + + +def test_update_generative_question_config_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_question_config), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.update_generative_question_config() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert ( + args[0] + == generative_question_service.UpdateGenerativeQuestionConfigRequest() + ) + + +def test_update_generative_question_config_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = generative_question_service.UpdateGenerativeQuestionConfigRequest() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_question_config), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.update_generative_question_config(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert ( + args[0] + == generative_question_service.UpdateGenerativeQuestionConfigRequest() + ) + + +def test_update_generative_question_config_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.update_generative_question_config + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.update_generative_question_config + ] = mock_rpc + request = {} + client.update_generative_question_config(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.update_generative_question_config(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_update_generative_question_config_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_question_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question.GenerativeQuestionConfig( + catalog="catalog_value", + facet="facet_value", + generated_question="generated_question_value", + final_question="final_question_value", + example_values=["example_values_value"], + frequency=0.978, + allowed_in_conversation=True, + ) + ) + response = await client.update_generative_question_config() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert ( + args[0] + == generative_question_service.UpdateGenerativeQuestionConfigRequest() + ) + + +@pytest.mark.asyncio +async def test_update_generative_question_config_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.update_generative_question_config + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.AsyncMock() + mock_rpc.return_value = mock.Mock() + client._client._transport._wrapped_methods[ + client._client._transport.update_generative_question_config + ] = mock_rpc + + request = {} + await client.update_generative_question_config(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + await client.update_generative_question_config(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_update_generative_question_config_async( + transport: str = "grpc_asyncio", + request_type=generative_question_service.UpdateGenerativeQuestionConfigRequest, +): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_question_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question.GenerativeQuestionConfig( + catalog="catalog_value", + facet="facet_value", + generated_question="generated_question_value", + final_question="final_question_value", + example_values=["example_values_value"], + frequency=0.978, + allowed_in_conversation=True, + ) + ) + response = await client.update_generative_question_config(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = generative_question_service.UpdateGenerativeQuestionConfigRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, generative_question.GenerativeQuestionConfig) + assert response.catalog == "catalog_value" + assert response.facet == "facet_value" + assert response.generated_question == "generated_question_value" + assert response.final_question == "final_question_value" + assert response.example_values == ["example_values_value"] + assert math.isclose(response.frequency, 0.978, rel_tol=1e-6) + assert response.allowed_in_conversation is True + + +@pytest.mark.asyncio +async def test_update_generative_question_config_async_from_dict(): + await test_update_generative_question_config_async(request_type=dict) + + +def test_update_generative_question_config_field_headers(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = generative_question_service.UpdateGenerativeQuestionConfigRequest() + + request.generative_question_config.catalog = "catalog_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_question_config), "__call__" + ) as call: + call.return_value = generative_question.GenerativeQuestionConfig() + client.update_generative_question_config(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "generative_question_config.catalog=catalog_value", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_update_generative_question_config_field_headers_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = generative_question_service.UpdateGenerativeQuestionConfigRequest() + + request.generative_question_config.catalog = "catalog_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_question_config), "__call__" + ) as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question.GenerativeQuestionConfig() + ) + await client.update_generative_question_config(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "generative_question_config.catalog=catalog_value", + ) in kw["metadata"] + + +def test_update_generative_question_config_flattened(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_question_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = generative_question.GenerativeQuestionConfig() + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.update_generative_question_config( + generative_question_config=generative_question.GenerativeQuestionConfig( + catalog="catalog_value" + ), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + arg = args[0].generative_question_config + mock_val = generative_question.GenerativeQuestionConfig(catalog="catalog_value") + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val + + +def test_update_generative_question_config_flattened_error(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.update_generative_question_config( + generative_question_service.UpdateGenerativeQuestionConfigRequest(), + generative_question_config=generative_question.GenerativeQuestionConfig( + catalog="catalog_value" + ), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + +@pytest.mark.asyncio +async def test_update_generative_question_config_flattened_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_generative_question_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = generative_question.GenerativeQuestionConfig() + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question.GenerativeQuestionConfig() + ) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.update_generative_question_config( + generative_question_config=generative_question.GenerativeQuestionConfig( + catalog="catalog_value" + ), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + arg = args[0].generative_question_config + mock_val = generative_question.GenerativeQuestionConfig(catalog="catalog_value") + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val + + +@pytest.mark.asyncio +async def test_update_generative_question_config_flattened_error_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + await client.update_generative_question_config( + generative_question_service.UpdateGenerativeQuestionConfigRequest(), + generative_question_config=generative_question.GenerativeQuestionConfig( + catalog="catalog_value" + ), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + +@pytest.mark.parametrize( + "request_type", + [ + generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest, + dict, + ], +) +def test_batch_update_generative_question_configs( + request_type, transport: str = "grpc" +): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.batch_update_generative_question_configs), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = ( + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse() + ) + response = client.batch_update_generative_question_configs(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = ( + generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest() + ) + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance( + response, + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse, + ) + + +def test_batch_update_generative_question_configs_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.batch_update_generative_question_configs), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.batch_update_generative_question_configs() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert ( + args[0] + == generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest() + ) + + +def test_batch_update_generative_question_configs_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest( + parent="parent_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.batch_update_generative_question_configs), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.batch_update_generative_question_configs(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[ + 0 + ] == generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest( + parent="parent_value", + ) + + +def test_batch_update_generative_question_configs_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.batch_update_generative_question_configs + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.batch_update_generative_question_configs + ] = mock_rpc + request = {} + client.batch_update_generative_question_configs(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.batch_update_generative_question_configs(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_batch_update_generative_question_configs_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.batch_update_generative_question_configs), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse() + ) + response = await client.batch_update_generative_question_configs() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert ( + args[0] + == generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest() + ) + + +@pytest.mark.asyncio +async def test_batch_update_generative_question_configs_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.batch_update_generative_question_configs + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.AsyncMock() + mock_rpc.return_value = mock.Mock() + client._client._transport._wrapped_methods[ + client._client._transport.batch_update_generative_question_configs + ] = mock_rpc + + request = {} + await client.batch_update_generative_question_configs(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + await client.batch_update_generative_question_configs(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_batch_update_generative_question_configs_async( + transport: str = "grpc_asyncio", + request_type=generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest, +): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.batch_update_generative_question_configs), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse() + ) + response = await client.batch_update_generative_question_configs(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = ( + generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest() + ) + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance( + response, + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse, + ) + + +@pytest.mark.asyncio +async def test_batch_update_generative_question_configs_async_from_dict(): + await test_batch_update_generative_question_configs_async(request_type=dict) + + +def test_batch_update_generative_question_configs_field_headers(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest() + + request.parent = "parent_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.batch_update_generative_question_configs), "__call__" + ) as call: + call.return_value = ( + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse() + ) + client.batch_update_generative_question_configs(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "parent=parent_value", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_batch_update_generative_question_configs_field_headers_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest() + + request.parent = "parent_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.batch_update_generative_question_configs), "__call__" + ) as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse() + ) + await client.batch_update_generative_question_configs(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "parent=parent_value", + ) in kw["metadata"] + + +def test_batch_update_generative_question_configs_flattened(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.batch_update_generative_question_configs), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = ( + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse() + ) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.batch_update_generative_question_configs( + parent="parent_value", + requests=[ + generative_question_service.UpdateGenerativeQuestionConfigRequest( + generative_question_config=generative_question.GenerativeQuestionConfig( + catalog="catalog_value" + ) + ) + ], + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].requests + mock_val = [ + generative_question_service.UpdateGenerativeQuestionConfigRequest( + generative_question_config=generative_question.GenerativeQuestionConfig( + catalog="catalog_value" + ) + ) + ] + assert arg == mock_val + + +def test_batch_update_generative_question_configs_flattened_error(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.batch_update_generative_question_configs( + generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest(), + parent="parent_value", + requests=[ + generative_question_service.UpdateGenerativeQuestionConfigRequest( + generative_question_config=generative_question.GenerativeQuestionConfig( + catalog="catalog_value" + ) + ) + ], + ) + + +@pytest.mark.asyncio +async def test_batch_update_generative_question_configs_flattened_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.batch_update_generative_question_configs), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = ( + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse() + ) + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse() + ) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.batch_update_generative_question_configs( + parent="parent_value", + requests=[ + generative_question_service.UpdateGenerativeQuestionConfigRequest( + generative_question_config=generative_question.GenerativeQuestionConfig( + catalog="catalog_value" + ) + ) + ], + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + arg = args[0].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].requests + mock_val = [ + generative_question_service.UpdateGenerativeQuestionConfigRequest( + generative_question_config=generative_question.GenerativeQuestionConfig( + catalog="catalog_value" + ) + ) + ] + assert arg == mock_val + + +@pytest.mark.asyncio +async def test_batch_update_generative_question_configs_flattened_error_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + await client.batch_update_generative_question_configs( + generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest(), + parent="parent_value", + requests=[ + generative_question_service.UpdateGenerativeQuestionConfigRequest( + generative_question_config=generative_question.GenerativeQuestionConfig( + catalog="catalog_value" + ) + ) + ], + ) + + +@pytest.mark.parametrize( + "request_type", + [ + generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest, + dict, + ], +) +def test_update_generative_questions_feature_config_rest(request_type): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = { + "generative_questions_feature_config": { + "catalog": "projects/sample1/locations/sample2/catalogs/sample3" + } + } + request_init["generative_questions_feature_config"] = { + "catalog": "projects/sample1/locations/sample2/catalogs/sample3", + "feature_enabled": True, + "minimum_products": 1743, + } + # The version of a generated dependency at test runtime may differ from the version used during generation. + # Delete any fields which are not present in the current runtime dependency + # See https://github.com/googleapis/gapic-generator-python/issues/1748 + + # Determine if the message type is proto-plus or protobuf + test_field = generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest.meta.fields[ + "generative_questions_feature_config" + ] + + def get_message_fields(field): + # Given a field which is a message (composite type), return a list with + # all the fields of the message. + # If the field is not a composite type, return an empty list. + message_fields = [] + + if hasattr(field, "message") and field.message: + is_field_type_proto_plus_type = not hasattr(field.message, "DESCRIPTOR") + + if is_field_type_proto_plus_type: + message_fields = field.message.meta.fields.values() + # Add `# pragma: NO COVER` because there may not be any `*_pb2` field types + else: # pragma: NO COVER + message_fields = field.message.DESCRIPTOR.fields + return message_fields + + runtime_nested_fields = [ + (field.name, nested_field.name) + for field in get_message_fields(test_field) + for nested_field in get_message_fields(field) + ] + + subfields_not_in_runtime = [] + + # For each item in the sample request, create a list of sub fields which are not present at runtime + # Add `# pragma: NO COVER` because this test code will not run if all subfields are present at runtime + for field, value in request_init[ + "generative_questions_feature_config" + ].items(): # pragma: NO COVER + result = None + is_repeated = False + # For repeated fields + if isinstance(value, list) and len(value): + is_repeated = True + result = value[0] + # For fields where the type is another message + if isinstance(value, dict): + result = value + + if result and hasattr(result, "keys"): + for subfield in result.keys(): + if (field, subfield) not in runtime_nested_fields: + subfields_not_in_runtime.append( + { + "field": field, + "subfield": subfield, + "is_repeated": is_repeated, + } + ) + + # Remove fields from the sample request which are not present in the runtime version of the dependency + # Add `# pragma: NO COVER` because this test code will not run if all subfields are present at runtime + for subfield_to_delete in subfields_not_in_runtime: # pragma: NO COVER + field = subfield_to_delete.get("field") + field_repeated = subfield_to_delete.get("is_repeated") + subfield = subfield_to_delete.get("subfield") + if subfield: + if field_repeated: + for i in range( + 0, len(request_init["generative_questions_feature_config"][field]) + ): + del request_init["generative_questions_feature_config"][field][i][ + subfield + ] + else: + del request_init["generative_questions_feature_config"][field][subfield] + request = request_type(**request_init) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = generative_question.GenerativeQuestionsFeatureConfig( + catalog="catalog_value", + feature_enabled=True, + minimum_products=1743, + ) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = generative_question.GenerativeQuestionsFeatureConfig.pb( + return_value + ) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + response = client.update_generative_questions_feature_config(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, generative_question.GenerativeQuestionsFeatureConfig) + assert response.catalog == "catalog_value" + assert response.feature_enabled is True + assert response.minimum_products == 1743 + + +def test_update_generative_questions_feature_config_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.update_generative_questions_feature_config + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.update_generative_questions_feature_config + ] = mock_rpc + + request = {} + client.update_generative_questions_feature_config(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.update_generative_questions_feature_config(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_update_generative_questions_feature_config_rest_required_fields( + request_type=generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest, +): + transport_class = transports.GenerativeQuestionServiceRestTransport + + request_init = {} + request = request_type(**request_init) + pb_request = request_type.pb(request) + jsonified_request = json.loads( + json_format.MessageToJson(pb_request, use_integers_for_enums=False) + ) + + # verify fields with default values are dropped + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).update_generative_questions_feature_config._get_unset_required_fields( + jsonified_request + ) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).update_generative_questions_feature_config._get_unset_required_fields( + jsonified_request + ) + # Check that path parameters and body parameters are not mixing in. + assert not set(unset_fields) - set(("update_mask",)) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = generative_question.GenerativeQuestionsFeatureConfig() + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # We need to mock transcode() because providing default values + # for required fields will fail the real version if the http_options + # expect actual values for those fields. + with mock.patch.object(path_template, "transcode") as transcode: + # A uri without fields and an empty body will force all the + # request fields to show up in the query_params. + pb_request = request_type.pb(request) + transcode_result = { + "uri": "v1/sample_method", + "method": "patch", + "query_params": pb_request, + } + transcode_result["body"] = pb_request + transcode.return_value = transcode_result + + response_value = Response() + response_value.status_code = 200 + + # Convert return value to protobuf type + return_value = generative_question.GenerativeQuestionsFeatureConfig.pb( + return_value + ) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + response = client.update_generative_questions_feature_config(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_update_generative_questions_feature_config_rest_unset_required_fields(): + transport = transports.GenerativeQuestionServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = ( + transport.update_generative_questions_feature_config._get_unset_required_fields( + {} + ) + ) + assert set(unset_fields) == ( + set(("updateMask",)) & set(("generativeQuestionsFeatureConfig",)) + ) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_update_generative_questions_feature_config_rest_interceptors(null_interceptor): + transport = transports.GenerativeQuestionServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.GenerativeQuestionServiceRestInterceptor(), + ) + client = GenerativeQuestionServiceClient(transport=transport) + with mock.patch.object( + type(client.transport._session), "request" + ) as req, mock.patch.object( + path_template, "transcode" + ) as transcode, mock.patch.object( + transports.GenerativeQuestionServiceRestInterceptor, + "post_update_generative_questions_feature_config", + ) as post, mock.patch.object( + transports.GenerativeQuestionServiceRestInterceptor, + "pre_update_generative_questions_feature_config", + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest.pb( + generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest() + ) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = Response() + req.return_value.status_code = 200 + req.return_value.request = PreparedRequest() + req.return_value._content = ( + generative_question.GenerativeQuestionsFeatureConfig.to_json( + generative_question.GenerativeQuestionsFeatureConfig() + ) + ) + + request = ( + generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest() + ) + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = generative_question.GenerativeQuestionsFeatureConfig() + + client.update_generative_questions_feature_config( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_update_generative_questions_feature_config_rest_bad_request( + transport: str = "rest", + request_type=generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest, +): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = { + "generative_questions_feature_config": { + "catalog": "projects/sample1/locations/sample2/catalogs/sample3" + } + } + request = request_type(**request_init) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 400 + response_value.request = Request() + req.return_value = response_value + client.update_generative_questions_feature_config(request) + + +def test_update_generative_questions_feature_config_rest_flattened(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = generative_question.GenerativeQuestionsFeatureConfig() + + # get arguments that satisfy an http rule for this method + sample_request = { + "generative_questions_feature_config": { + "catalog": "projects/sample1/locations/sample2/catalogs/sample3" + } + } + + # get truthy value for each flattened field + mock_args = dict( + generative_questions_feature_config=generative_question.GenerativeQuestionsFeatureConfig( + catalog="catalog_value" + ), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + mock_args.update(sample_request) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = generative_question.GenerativeQuestionsFeatureConfig.pb( + return_value + ) + json_return_value = json_format.MessageToJson(return_value) + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + client.update_generative_questions_feature_config(**mock_args) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(req.mock_calls) == 1 + _, args, _ = req.mock_calls[0] + assert path_template.validate( + "%s/v2beta/{generative_questions_feature_config.catalog=projects/*/locations/*/catalogs/*}/generativeQuestionFeature" + % client.transport._host, + args[1], + ) + + +def test_update_generative_questions_feature_config_rest_flattened_error( + transport: str = "rest", +): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.update_generative_questions_feature_config( + generative_question_service.UpdateGenerativeQuestionsFeatureConfigRequest(), + generative_questions_feature_config=generative_question.GenerativeQuestionsFeatureConfig( + catalog="catalog_value" + ), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + +def test_update_generative_questions_feature_config_rest_error(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + +@pytest.mark.parametrize( + "request_type", + [ + generative_question_service.GetGenerativeQuestionsFeatureConfigRequest, + dict, + ], +) +def test_get_generative_questions_feature_config_rest(request_type): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = {"catalog": "projects/sample1/locations/sample2/catalogs/sample3"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = generative_question.GenerativeQuestionsFeatureConfig( + catalog="catalog_value", + feature_enabled=True, + minimum_products=1743, + ) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = generative_question.GenerativeQuestionsFeatureConfig.pb( + return_value + ) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + response = client.get_generative_questions_feature_config(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, generative_question.GenerativeQuestionsFeatureConfig) + assert response.catalog == "catalog_value" + assert response.feature_enabled is True + assert response.minimum_products == 1743 + + +def test_get_generative_questions_feature_config_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.get_generative_questions_feature_config + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.get_generative_questions_feature_config + ] = mock_rpc + + request = {} + client.get_generative_questions_feature_config(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.get_generative_questions_feature_config(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_get_generative_questions_feature_config_rest_required_fields( + request_type=generative_question_service.GetGenerativeQuestionsFeatureConfigRequest, +): + transport_class = transports.GenerativeQuestionServiceRestTransport + + request_init = {} + request_init["catalog"] = "" + request = request_type(**request_init) + pb_request = request_type.pb(request) + jsonified_request = json.loads( + json_format.MessageToJson(pb_request, use_integers_for_enums=False) + ) + + # verify fields with default values are dropped + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).get_generative_questions_feature_config._get_unset_required_fields( + jsonified_request + ) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + jsonified_request["catalog"] = "catalog_value" + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).get_generative_questions_feature_config._get_unset_required_fields( + jsonified_request + ) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + assert "catalog" in jsonified_request + assert jsonified_request["catalog"] == "catalog_value" + + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = generative_question.GenerativeQuestionsFeatureConfig() + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # We need to mock transcode() because providing default values + # for required fields will fail the real version if the http_options + # expect actual values for those fields. + with mock.patch.object(path_template, "transcode") as transcode: + # A uri without fields and an empty body will force all the + # request fields to show up in the query_params. + pb_request = request_type.pb(request) + transcode_result = { + "uri": "v1/sample_method", + "method": "get", + "query_params": pb_request, + } + transcode.return_value = transcode_result + + response_value = Response() + response_value.status_code = 200 + + # Convert return value to protobuf type + return_value = generative_question.GenerativeQuestionsFeatureConfig.pb( + return_value + ) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + response = client.get_generative_questions_feature_config(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_get_generative_questions_feature_config_rest_unset_required_fields(): + transport = transports.GenerativeQuestionServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = ( + transport.get_generative_questions_feature_config._get_unset_required_fields({}) + ) + assert set(unset_fields) == (set(()) & set(("catalog",))) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_get_generative_questions_feature_config_rest_interceptors(null_interceptor): + transport = transports.GenerativeQuestionServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.GenerativeQuestionServiceRestInterceptor(), + ) + client = GenerativeQuestionServiceClient(transport=transport) + with mock.patch.object( + type(client.transport._session), "request" + ) as req, mock.patch.object( + path_template, "transcode" + ) as transcode, mock.patch.object( + transports.GenerativeQuestionServiceRestInterceptor, + "post_get_generative_questions_feature_config", + ) as post, mock.patch.object( + transports.GenerativeQuestionServiceRestInterceptor, + "pre_get_generative_questions_feature_config", + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = ( + generative_question_service.GetGenerativeQuestionsFeatureConfigRequest.pb( + generative_question_service.GetGenerativeQuestionsFeatureConfigRequest() + ) + ) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = Response() + req.return_value.status_code = 200 + req.return_value.request = PreparedRequest() + req.return_value._content = ( + generative_question.GenerativeQuestionsFeatureConfig.to_json( + generative_question.GenerativeQuestionsFeatureConfig() + ) + ) + + request = ( + generative_question_service.GetGenerativeQuestionsFeatureConfigRequest() + ) + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = generative_question.GenerativeQuestionsFeatureConfig() + + client.get_generative_questions_feature_config( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_get_generative_questions_feature_config_rest_bad_request( + transport: str = "rest", + request_type=generative_question_service.GetGenerativeQuestionsFeatureConfigRequest, +): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = {"catalog": "projects/sample1/locations/sample2/catalogs/sample3"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 400 + response_value.request = Request() + req.return_value = response_value + client.get_generative_questions_feature_config(request) + + +def test_get_generative_questions_feature_config_rest_flattened(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = generative_question.GenerativeQuestionsFeatureConfig() + + # get arguments that satisfy an http rule for this method + sample_request = { + "catalog": "projects/sample1/locations/sample2/catalogs/sample3" + } + + # get truthy value for each flattened field + mock_args = dict( + catalog="catalog_value", + ) + mock_args.update(sample_request) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = generative_question.GenerativeQuestionsFeatureConfig.pb( + return_value + ) + json_return_value = json_format.MessageToJson(return_value) + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + client.get_generative_questions_feature_config(**mock_args) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(req.mock_calls) == 1 + _, args, _ = req.mock_calls[0] + assert path_template.validate( + "%s/v2beta/{catalog=projects/*/locations/*/catalogs/*}/generativeQuestionFeature" + % client.transport._host, + args[1], + ) + + +def test_get_generative_questions_feature_config_rest_flattened_error( + transport: str = "rest", +): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.get_generative_questions_feature_config( + generative_question_service.GetGenerativeQuestionsFeatureConfigRequest(), + catalog="catalog_value", + ) + + +def test_get_generative_questions_feature_config_rest_error(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + +@pytest.mark.parametrize( + "request_type", + [ + generative_question_service.ListGenerativeQuestionConfigsRequest, + dict, + ], +) +def test_list_generative_question_configs_rest(request_type): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = {"parent": "projects/sample1/locations/sample2/catalogs/sample3"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = ( + generative_question_service.ListGenerativeQuestionConfigsResponse() + ) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = ( + generative_question_service.ListGenerativeQuestionConfigsResponse.pb( + return_value + ) + ) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + response = client.list_generative_question_configs(request) + + # Establish that the response is the type that we expect. + assert isinstance( + response, generative_question_service.ListGenerativeQuestionConfigsResponse + ) + + +def test_list_generative_question_configs_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.list_generative_question_configs + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.list_generative_question_configs + ] = mock_rpc + + request = {} + client.list_generative_question_configs(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.list_generative_question_configs(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_list_generative_question_configs_rest_required_fields( + request_type=generative_question_service.ListGenerativeQuestionConfigsRequest, +): + transport_class = transports.GenerativeQuestionServiceRestTransport + + request_init = {} + request_init["parent"] = "" + request = request_type(**request_init) + pb_request = request_type.pb(request) + jsonified_request = json.loads( + json_format.MessageToJson(pb_request, use_integers_for_enums=False) + ) + + # verify fields with default values are dropped + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).list_generative_question_configs._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + jsonified_request["parent"] = "parent_value" + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).list_generative_question_configs._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + assert "parent" in jsonified_request + assert jsonified_request["parent"] == "parent_value" + + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = generative_question_service.ListGenerativeQuestionConfigsResponse() + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # We need to mock transcode() because providing default values + # for required fields will fail the real version if the http_options + # expect actual values for those fields. + with mock.patch.object(path_template, "transcode") as transcode: + # A uri without fields and an empty body will force all the + # request fields to show up in the query_params. + pb_request = request_type.pb(request) + transcode_result = { + "uri": "v1/sample_method", + "method": "get", + "query_params": pb_request, + } + transcode.return_value = transcode_result + + response_value = Response() + response_value.status_code = 200 + + # Convert return value to protobuf type + return_value = ( + generative_question_service.ListGenerativeQuestionConfigsResponse.pb( + return_value + ) + ) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + response = client.list_generative_question_configs(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_list_generative_question_configs_rest_unset_required_fields(): + transport = transports.GenerativeQuestionServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = ( + transport.list_generative_question_configs._get_unset_required_fields({}) + ) + assert set(unset_fields) == (set(()) & set(("parent",))) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_list_generative_question_configs_rest_interceptors(null_interceptor): + transport = transports.GenerativeQuestionServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.GenerativeQuestionServiceRestInterceptor(), + ) + client = GenerativeQuestionServiceClient(transport=transport) + with mock.patch.object( + type(client.transport._session), "request" + ) as req, mock.patch.object( + path_template, "transcode" + ) as transcode, mock.patch.object( + transports.GenerativeQuestionServiceRestInterceptor, + "post_list_generative_question_configs", + ) as post, mock.patch.object( + transports.GenerativeQuestionServiceRestInterceptor, + "pre_list_generative_question_configs", + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = ( + generative_question_service.ListGenerativeQuestionConfigsRequest.pb( + generative_question_service.ListGenerativeQuestionConfigsRequest() + ) + ) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = Response() + req.return_value.status_code = 200 + req.return_value.request = PreparedRequest() + req.return_value._content = ( + generative_question_service.ListGenerativeQuestionConfigsResponse.to_json( + generative_question_service.ListGenerativeQuestionConfigsResponse() + ) + ) + + request = generative_question_service.ListGenerativeQuestionConfigsRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = ( + generative_question_service.ListGenerativeQuestionConfigsResponse() + ) + + client.list_generative_question_configs( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_list_generative_question_configs_rest_bad_request( + transport: str = "rest", + request_type=generative_question_service.ListGenerativeQuestionConfigsRequest, +): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = {"parent": "projects/sample1/locations/sample2/catalogs/sample3"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 400 + response_value.request = Request() + req.return_value = response_value + client.list_generative_question_configs(request) + + +def test_list_generative_question_configs_rest_flattened(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = ( + generative_question_service.ListGenerativeQuestionConfigsResponse() + ) + + # get arguments that satisfy an http rule for this method + sample_request = { + "parent": "projects/sample1/locations/sample2/catalogs/sample3" + } + + # get truthy value for each flattened field + mock_args = dict( + parent="parent_value", + ) + mock_args.update(sample_request) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = ( + generative_question_service.ListGenerativeQuestionConfigsResponse.pb( + return_value + ) + ) + json_return_value = json_format.MessageToJson(return_value) + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + client.list_generative_question_configs(**mock_args) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(req.mock_calls) == 1 + _, args, _ = req.mock_calls[0] + assert path_template.validate( + "%s/v2beta/{parent=projects/*/locations/*/catalogs/*}/generativeQuestions" + % client.transport._host, + args[1], + ) + + +def test_list_generative_question_configs_rest_flattened_error(transport: str = "rest"): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.list_generative_question_configs( + generative_question_service.ListGenerativeQuestionConfigsRequest(), + parent="parent_value", + ) + + +def test_list_generative_question_configs_rest_error(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + +@pytest.mark.parametrize( + "request_type", + [ + generative_question_service.UpdateGenerativeQuestionConfigRequest, + dict, + ], +) +def test_update_generative_question_config_rest(request_type): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = { + "generative_question_config": { + "catalog": "projects/sample1/locations/sample2/catalogs/sample3" + } + } + request_init["generative_question_config"] = { + "catalog": "projects/sample1/locations/sample2/catalogs/sample3", + "facet": "facet_value", + "generated_question": "generated_question_value", + "final_question": "final_question_value", + "example_values": ["example_values_value1", "example_values_value2"], + "frequency": 0.978, + "allowed_in_conversation": True, + } + # The version of a generated dependency at test runtime may differ from the version used during generation. + # Delete any fields which are not present in the current runtime dependency + # See https://github.com/googleapis/gapic-generator-python/issues/1748 + + # Determine if the message type is proto-plus or protobuf + test_field = ( + generative_question_service.UpdateGenerativeQuestionConfigRequest.meta.fields[ + "generative_question_config" + ] + ) + + def get_message_fields(field): + # Given a field which is a message (composite type), return a list with + # all the fields of the message. + # If the field is not a composite type, return an empty list. + message_fields = [] + + if hasattr(field, "message") and field.message: + is_field_type_proto_plus_type = not hasattr(field.message, "DESCRIPTOR") + + if is_field_type_proto_plus_type: + message_fields = field.message.meta.fields.values() + # Add `# pragma: NO COVER` because there may not be any `*_pb2` field types + else: # pragma: NO COVER + message_fields = field.message.DESCRIPTOR.fields + return message_fields + + runtime_nested_fields = [ + (field.name, nested_field.name) + for field in get_message_fields(test_field) + for nested_field in get_message_fields(field) + ] + + subfields_not_in_runtime = [] + + # For each item in the sample request, create a list of sub fields which are not present at runtime + # Add `# pragma: NO COVER` because this test code will not run if all subfields are present at runtime + for field, value in request_init[ + "generative_question_config" + ].items(): # pragma: NO COVER + result = None + is_repeated = False + # For repeated fields + if isinstance(value, list) and len(value): + is_repeated = True + result = value[0] + # For fields where the type is another message + if isinstance(value, dict): + result = value + + if result and hasattr(result, "keys"): + for subfield in result.keys(): + if (field, subfield) not in runtime_nested_fields: + subfields_not_in_runtime.append( + { + "field": field, + "subfield": subfield, + "is_repeated": is_repeated, + } + ) + + # Remove fields from the sample request which are not present in the runtime version of the dependency + # Add `# pragma: NO COVER` because this test code will not run if all subfields are present at runtime + for subfield_to_delete in subfields_not_in_runtime: # pragma: NO COVER + field = subfield_to_delete.get("field") + field_repeated = subfield_to_delete.get("is_repeated") + subfield = subfield_to_delete.get("subfield") + if subfield: + if field_repeated: + for i in range( + 0, len(request_init["generative_question_config"][field]) + ): + del request_init["generative_question_config"][field][i][subfield] + else: + del request_init["generative_question_config"][field][subfield] + request = request_type(**request_init) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = generative_question.GenerativeQuestionConfig( + catalog="catalog_value", + facet="facet_value", + generated_question="generated_question_value", + final_question="final_question_value", + example_values=["example_values_value"], + frequency=0.978, + allowed_in_conversation=True, + ) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = generative_question.GenerativeQuestionConfig.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + response = client.update_generative_question_config(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, generative_question.GenerativeQuestionConfig) + assert response.catalog == "catalog_value" + assert response.facet == "facet_value" + assert response.generated_question == "generated_question_value" + assert response.final_question == "final_question_value" + assert response.example_values == ["example_values_value"] + assert math.isclose(response.frequency, 0.978, rel_tol=1e-6) + assert response.allowed_in_conversation is True + + +def test_update_generative_question_config_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.update_generative_question_config + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.update_generative_question_config + ] = mock_rpc + + request = {} + client.update_generative_question_config(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.update_generative_question_config(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_update_generative_question_config_rest_required_fields( + request_type=generative_question_service.UpdateGenerativeQuestionConfigRequest, +): + transport_class = transports.GenerativeQuestionServiceRestTransport + + request_init = {} + request = request_type(**request_init) + pb_request = request_type.pb(request) + jsonified_request = json.loads( + json_format.MessageToJson(pb_request, use_integers_for_enums=False) + ) + + # verify fields with default values are dropped + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).update_generative_question_config._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).update_generative_question_config._get_unset_required_fields(jsonified_request) + # Check that path parameters and body parameters are not mixing in. + assert not set(unset_fields) - set(("update_mask",)) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = generative_question.GenerativeQuestionConfig() + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # We need to mock transcode() because providing default values + # for required fields will fail the real version if the http_options + # expect actual values for those fields. + with mock.patch.object(path_template, "transcode") as transcode: + # A uri without fields and an empty body will force all the + # request fields to show up in the query_params. + pb_request = request_type.pb(request) + transcode_result = { + "uri": "v1/sample_method", + "method": "patch", + "query_params": pb_request, + } + transcode_result["body"] = pb_request + transcode.return_value = transcode_result + + response_value = Response() + response_value.status_code = 200 + + # Convert return value to protobuf type + return_value = generative_question.GenerativeQuestionConfig.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + response = client.update_generative_question_config(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_update_generative_question_config_rest_unset_required_fields(): + transport = transports.GenerativeQuestionServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = ( + transport.update_generative_question_config._get_unset_required_fields({}) + ) + assert set(unset_fields) == ( + set(("updateMask",)) & set(("generativeQuestionConfig",)) + ) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_update_generative_question_config_rest_interceptors(null_interceptor): + transport = transports.GenerativeQuestionServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.GenerativeQuestionServiceRestInterceptor(), + ) + client = GenerativeQuestionServiceClient(transport=transport) + with mock.patch.object( + type(client.transport._session), "request" + ) as req, mock.patch.object( + path_template, "transcode" + ) as transcode, mock.patch.object( + transports.GenerativeQuestionServiceRestInterceptor, + "post_update_generative_question_config", + ) as post, mock.patch.object( + transports.GenerativeQuestionServiceRestInterceptor, + "pre_update_generative_question_config", + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = ( + generative_question_service.UpdateGenerativeQuestionConfigRequest.pb( + generative_question_service.UpdateGenerativeQuestionConfigRequest() + ) + ) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = Response() + req.return_value.status_code = 200 + req.return_value.request = PreparedRequest() + req.return_value._content = ( + generative_question.GenerativeQuestionConfig.to_json( + generative_question.GenerativeQuestionConfig() + ) + ) + + request = generative_question_service.UpdateGenerativeQuestionConfigRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = generative_question.GenerativeQuestionConfig() + + client.update_generative_question_config( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_update_generative_question_config_rest_bad_request( + transport: str = "rest", + request_type=generative_question_service.UpdateGenerativeQuestionConfigRequest, +): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = { + "generative_question_config": { + "catalog": "projects/sample1/locations/sample2/catalogs/sample3" + } + } + request = request_type(**request_init) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 400 + response_value.request = Request() + req.return_value = response_value + client.update_generative_question_config(request) + + +def test_update_generative_question_config_rest_flattened(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = generative_question.GenerativeQuestionConfig() + + # get arguments that satisfy an http rule for this method + sample_request = { + "generative_question_config": { + "catalog": "projects/sample1/locations/sample2/catalogs/sample3" + } + } + + # get truthy value for each flattened field + mock_args = dict( + generative_question_config=generative_question.GenerativeQuestionConfig( + catalog="catalog_value" + ), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + mock_args.update(sample_request) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = generative_question.GenerativeQuestionConfig.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + client.update_generative_question_config(**mock_args) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(req.mock_calls) == 1 + _, args, _ = req.mock_calls[0] + assert path_template.validate( + "%s/v2beta/{generative_question_config.catalog=projects/*/locations/*/catalogs/*}/generativeQuestion" + % client.transport._host, + args[1], + ) + + +def test_update_generative_question_config_rest_flattened_error( + transport: str = "rest", +): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.update_generative_question_config( + generative_question_service.UpdateGenerativeQuestionConfigRequest(), + generative_question_config=generative_question.GenerativeQuestionConfig( + catalog="catalog_value" + ), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + +def test_update_generative_question_config_rest_error(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + +@pytest.mark.parametrize( + "request_type", + [ + generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest, + dict, + ], +) +def test_batch_update_generative_question_configs_rest(request_type): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = {"parent": "projects/sample1/locations/sample2/catalogs/sample3"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = ( + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse() + ) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = ( + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse.pb( + return_value + ) + ) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + response = client.batch_update_generative_question_configs(request) + + # Establish that the response is the type that we expect. + assert isinstance( + response, + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse, + ) + + +def test_batch_update_generative_question_configs_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.batch_update_generative_question_configs + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.batch_update_generative_question_configs + ] = mock_rpc + + request = {} + client.batch_update_generative_question_configs(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.batch_update_generative_question_configs(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_batch_update_generative_question_configs_rest_required_fields( + request_type=generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest, +): + transport_class = transports.GenerativeQuestionServiceRestTransport + + request_init = {} + request = request_type(**request_init) + pb_request = request_type.pb(request) + jsonified_request = json.loads( + json_format.MessageToJson(pb_request, use_integers_for_enums=False) + ) + + # verify fields with default values are dropped + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).batch_update_generative_question_configs._get_unset_required_fields( + jsonified_request + ) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).batch_update_generative_question_configs._get_unset_required_fields( + jsonified_request + ) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = ( + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse() + ) + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # We need to mock transcode() because providing default values + # for required fields will fail the real version if the http_options + # expect actual values for those fields. + with mock.patch.object(path_template, "transcode") as transcode: + # A uri without fields and an empty body will force all the + # request fields to show up in the query_params. + pb_request = request_type.pb(request) + transcode_result = { + "uri": "v1/sample_method", + "method": "post", + "query_params": pb_request, + } + transcode_result["body"] = pb_request + transcode.return_value = transcode_result + + response_value = Response() + response_value.status_code = 200 + + # Convert return value to protobuf type + return_value = generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse.pb( + return_value + ) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + response = client.batch_update_generative_question_configs(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_batch_update_generative_question_configs_rest_unset_required_fields(): + transport = transports.GenerativeQuestionServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = ( + transport.batch_update_generative_question_configs._get_unset_required_fields( + {} + ) + ) + assert set(unset_fields) == (set(()) & set(("requests",))) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_batch_update_generative_question_configs_rest_interceptors(null_interceptor): + transport = transports.GenerativeQuestionServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.GenerativeQuestionServiceRestInterceptor(), + ) + client = GenerativeQuestionServiceClient(transport=transport) + with mock.patch.object( + type(client.transport._session), "request" + ) as req, mock.patch.object( + path_template, "transcode" + ) as transcode, mock.patch.object( + transports.GenerativeQuestionServiceRestInterceptor, + "post_batch_update_generative_question_configs", + ) as post, mock.patch.object( + transports.GenerativeQuestionServiceRestInterceptor, + "pre_batch_update_generative_question_configs", + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest.pb( + generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest() + ) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = Response() + req.return_value.status_code = 200 + req.return_value.request = PreparedRequest() + req.return_value._content = generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse.to_json( + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse() + ) + + request = ( + generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest() + ) + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = ( + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse() + ) + + client.batch_update_generative_question_configs( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_batch_update_generative_question_configs_rest_bad_request( + transport: str = "rest", + request_type=generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest, +): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = {"parent": "projects/sample1/locations/sample2/catalogs/sample3"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 400 + response_value.request = Request() + req.return_value = response_value + client.batch_update_generative_question_configs(request) + + +def test_batch_update_generative_question_configs_rest_flattened(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = ( + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse() + ) + + # get arguments that satisfy an http rule for this method + sample_request = { + "parent": "projects/sample1/locations/sample2/catalogs/sample3" + } + + # get truthy value for each flattened field + mock_args = dict( + parent="parent_value", + requests=[ + generative_question_service.UpdateGenerativeQuestionConfigRequest( + generative_question_config=generative_question.GenerativeQuestionConfig( + catalog="catalog_value" + ) + ) + ], + ) + mock_args.update(sample_request) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = ( + generative_question_service.BatchUpdateGenerativeQuestionConfigsResponse.pb( + return_value + ) + ) + json_return_value = json_format.MessageToJson(return_value) + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + client.batch_update_generative_question_configs(**mock_args) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(req.mock_calls) == 1 + _, args, _ = req.mock_calls[0] + assert path_template.validate( + "%s/v2beta/{parent=projects/*/locations/*/catalogs/*}/generativeQuestion:batchUpdate" + % client.transport._host, + args[1], + ) + + +def test_batch_update_generative_question_configs_rest_flattened_error( + transport: str = "rest", +): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.batch_update_generative_question_configs( + generative_question_service.BatchUpdateGenerativeQuestionConfigsRequest(), + parent="parent_value", + requests=[ + generative_question_service.UpdateGenerativeQuestionConfigRequest( + generative_question_config=generative_question.GenerativeQuestionConfig( + catalog="catalog_value" + ) + ) + ], + ) + + +def test_batch_update_generative_question_configs_rest_error(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + +def test_credentials_transport_error(): + # It is an error to provide credentials and a transport instance. + transport = transports.GenerativeQuestionServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + with pytest.raises(ValueError): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # It is an error to provide a credentials file and a transport instance. + transport = transports.GenerativeQuestionServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + with pytest.raises(ValueError): + client = GenerativeQuestionServiceClient( + client_options={"credentials_file": "credentials.json"}, + transport=transport, + ) + + # It is an error to provide an api_key and a transport instance. + transport = transports.GenerativeQuestionServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + options = client_options.ClientOptions() + options.api_key = "api_key" + with pytest.raises(ValueError): + client = GenerativeQuestionServiceClient( + client_options=options, + transport=transport, + ) + + # It is an error to provide an api_key and a credential. + options = client_options.ClientOptions() + options.api_key = "api_key" + with pytest.raises(ValueError): + client = GenerativeQuestionServiceClient( + client_options=options, credentials=ga_credentials.AnonymousCredentials() + ) + + # It is an error to provide scopes and a transport instance. + transport = transports.GenerativeQuestionServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + with pytest.raises(ValueError): + client = GenerativeQuestionServiceClient( + client_options={"scopes": ["1", "2"]}, + transport=transport, + ) + + +def test_transport_instance(): + # A client may be instantiated with a custom transport instance. + transport = transports.GenerativeQuestionServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + client = GenerativeQuestionServiceClient(transport=transport) + assert client.transport is transport + + +def test_transport_get_channel(): + # A client may be instantiated with a custom transport instance. + transport = transports.GenerativeQuestionServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + channel = transport.grpc_channel + assert channel + + transport = transports.GenerativeQuestionServiceGrpcAsyncIOTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + channel = transport.grpc_channel + assert channel + + +@pytest.mark.parametrize( + "transport_class", + [ + transports.GenerativeQuestionServiceGrpcTransport, + transports.GenerativeQuestionServiceGrpcAsyncIOTransport, + transports.GenerativeQuestionServiceRestTransport, + ], +) +def test_transport_adc(transport_class): + # Test default credentials are used if not provided. + with mock.patch.object(google.auth, "default") as adc: + adc.return_value = (ga_credentials.AnonymousCredentials(), None) + transport_class() + adc.assert_called_once() + + +@pytest.mark.parametrize( + "transport_name", + [ + "grpc", + "rest", + ], +) +def test_transport_kind(transport_name): + transport = GenerativeQuestionServiceClient.get_transport_class(transport_name)( + credentials=ga_credentials.AnonymousCredentials(), + ) + assert transport.kind == transport_name + + +def test_transport_grpc_default(): + # A client should use the gRPC transport by default. + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + assert isinstance( + client.transport, + transports.GenerativeQuestionServiceGrpcTransport, + ) + + +def test_generative_question_service_base_transport_error(): + # Passing both a credentials object and credentials_file should raise an error + with pytest.raises(core_exceptions.DuplicateCredentialArgs): + transport = transports.GenerativeQuestionServiceTransport( + credentials=ga_credentials.AnonymousCredentials(), + credentials_file="credentials.json", + ) + + +def test_generative_question_service_base_transport(): + # Instantiate the base transport. + with mock.patch( + "google.cloud.retail_v2beta.services.generative_question_service.transports.GenerativeQuestionServiceTransport.__init__" + ) as Transport: + Transport.return_value = None + transport = transports.GenerativeQuestionServiceTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Every method on the transport should just blindly + # raise NotImplementedError. + methods = ( + "update_generative_questions_feature_config", + "get_generative_questions_feature_config", + "list_generative_question_configs", + "update_generative_question_config", + "batch_update_generative_question_configs", + "get_operation", + "list_operations", + ) + for method in methods: + with pytest.raises(NotImplementedError): + getattr(transport, method)(request=object()) + + with pytest.raises(NotImplementedError): + transport.close() + + # Catch all for all remaining methods and properties + remainder = [ + "kind", + ] + for r in remainder: + with pytest.raises(NotImplementedError): + getattr(transport, r)() + + +def test_generative_question_service_base_transport_with_credentials_file(): + # Instantiate the base transport with a credentials file + with mock.patch.object( + google.auth, "load_credentials_from_file", autospec=True + ) as load_creds, mock.patch( + "google.cloud.retail_v2beta.services.generative_question_service.transports.GenerativeQuestionServiceTransport._prep_wrapped_messages" + ) as Transport: + Transport.return_value = None + load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) + transport = transports.GenerativeQuestionServiceTransport( + credentials_file="credentials.json", + quota_project_id="octopus", + ) + load_creds.assert_called_once_with( + "credentials.json", + scopes=None, + default_scopes=("https://www.googleapis.com/auth/cloud-platform",), + quota_project_id="octopus", + ) + + +def test_generative_question_service_base_transport_with_adc(): + # Test the default credentials are used if credentials and credentials_file are None. + with mock.patch.object(google.auth, "default", autospec=True) as adc, mock.patch( + "google.cloud.retail_v2beta.services.generative_question_service.transports.GenerativeQuestionServiceTransport._prep_wrapped_messages" + ) as Transport: + Transport.return_value = None + adc.return_value = (ga_credentials.AnonymousCredentials(), None) + transport = transports.GenerativeQuestionServiceTransport() + adc.assert_called_once() + + +def test_generative_question_service_auth_adc(): + # If no credentials are provided, we should use ADC credentials. + with mock.patch.object(google.auth, "default", autospec=True) as adc: + adc.return_value = (ga_credentials.AnonymousCredentials(), None) + GenerativeQuestionServiceClient() + adc.assert_called_once_with( + scopes=None, + default_scopes=("https://www.googleapis.com/auth/cloud-platform",), + quota_project_id=None, + ) + + +@pytest.mark.parametrize( + "transport_class", + [ + transports.GenerativeQuestionServiceGrpcTransport, + transports.GenerativeQuestionServiceGrpcAsyncIOTransport, + ], +) +def test_generative_question_service_transport_auth_adc(transport_class): + # If credentials and host are not provided, the transport class should use + # ADC credentials. + with mock.patch.object(google.auth, "default", autospec=True) as adc: + adc.return_value = (ga_credentials.AnonymousCredentials(), None) + transport_class(quota_project_id="octopus", scopes=["1", "2"]) + adc.assert_called_once_with( + scopes=["1", "2"], + default_scopes=("https://www.googleapis.com/auth/cloud-platform",), + quota_project_id="octopus", + ) + + +@pytest.mark.parametrize( + "transport_class", + [ + transports.GenerativeQuestionServiceGrpcTransport, + transports.GenerativeQuestionServiceGrpcAsyncIOTransport, + transports.GenerativeQuestionServiceRestTransport, + ], +) +def test_generative_question_service_transport_auth_gdch_credentials(transport_class): + host = "https://language.com" + api_audience_tests = [None, "https://language2.com"] + api_audience_expect = [host, "https://language2.com"] + for t, e in zip(api_audience_tests, api_audience_expect): + with mock.patch.object(google.auth, "default", autospec=True) as adc: + gdch_mock = mock.MagicMock() + type(gdch_mock).with_gdch_audience = mock.PropertyMock( + return_value=gdch_mock + ) + adc.return_value = (gdch_mock, None) + transport_class(host=host, api_audience=t) + gdch_mock.with_gdch_audience.assert_called_once_with(e) + + +@pytest.mark.parametrize( + "transport_class,grpc_helpers", + [ + (transports.GenerativeQuestionServiceGrpcTransport, grpc_helpers), + (transports.GenerativeQuestionServiceGrpcAsyncIOTransport, grpc_helpers_async), + ], +) +def test_generative_question_service_transport_create_channel( + transport_class, grpc_helpers +): + # If credentials and host are not provided, the transport class should use + # ADC credentials. + with mock.patch.object( + google.auth, "default", autospec=True + ) as adc, mock.patch.object( + grpc_helpers, "create_channel", autospec=True + ) as create_channel: + creds = ga_credentials.AnonymousCredentials() + adc.return_value = (creds, None) + transport_class(quota_project_id="octopus", scopes=["1", "2"]) + + create_channel.assert_called_with( + "retail.googleapis.com:443", + credentials=creds, + credentials_file=None, + quota_project_id="octopus", + default_scopes=("https://www.googleapis.com/auth/cloud-platform",), + scopes=["1", "2"], + default_host="retail.googleapis.com", + ssl_credentials=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + +@pytest.mark.parametrize( + "transport_class", + [ + transports.GenerativeQuestionServiceGrpcTransport, + transports.GenerativeQuestionServiceGrpcAsyncIOTransport, + ], +) +def test_generative_question_service_grpc_transport_client_cert_source_for_mtls( + transport_class, +): + cred = ga_credentials.AnonymousCredentials() + + # Check ssl_channel_credentials is used if provided. + with mock.patch.object(transport_class, "create_channel") as mock_create_channel: + mock_ssl_channel_creds = mock.Mock() + transport_class( + host="squid.clam.whelk", + credentials=cred, + ssl_channel_credentials=mock_ssl_channel_creds, + ) + mock_create_channel.assert_called_once_with( + "squid.clam.whelk:443", + credentials=cred, + credentials_file=None, + scopes=None, + ssl_credentials=mock_ssl_channel_creds, + quota_project_id=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Check if ssl_channel_credentials is not provided, then client_cert_source_for_mtls + # is used. + with mock.patch.object(transport_class, "create_channel", return_value=mock.Mock()): + with mock.patch("grpc.ssl_channel_credentials") as mock_ssl_cred: + transport_class( + credentials=cred, + client_cert_source_for_mtls=client_cert_source_callback, + ) + expected_cert, expected_key = client_cert_source_callback() + mock_ssl_cred.assert_called_once_with( + certificate_chain=expected_cert, private_key=expected_key + ) + + +def test_generative_question_service_http_transport_client_cert_source_for_mtls(): + cred = ga_credentials.AnonymousCredentials() + with mock.patch( + "google.auth.transport.requests.AuthorizedSession.configure_mtls_channel" + ) as mock_configure_mtls_channel: + transports.GenerativeQuestionServiceRestTransport( + credentials=cred, client_cert_source_for_mtls=client_cert_source_callback + ) + mock_configure_mtls_channel.assert_called_once_with(client_cert_source_callback) + + +@pytest.mark.parametrize( + "transport_name", + [ + "grpc", + "grpc_asyncio", + "rest", + ], +) +def test_generative_question_service_host_no_port(transport_name): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + client_options=client_options.ClientOptions( + api_endpoint="retail.googleapis.com" + ), + transport=transport_name, + ) + assert client.transport._host == ( + "retail.googleapis.com:443" + if transport_name in ["grpc", "grpc_asyncio"] + else "https://retail.googleapis.com" + ) + + +@pytest.mark.parametrize( + "transport_name", + [ + "grpc", + "grpc_asyncio", + "rest", + ], +) +def test_generative_question_service_host_with_port(transport_name): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + client_options=client_options.ClientOptions( + api_endpoint="retail.googleapis.com:8000" + ), + transport=transport_name, + ) + assert client.transport._host == ( + "retail.googleapis.com:8000" + if transport_name in ["grpc", "grpc_asyncio"] + else "https://retail.googleapis.com:8000" + ) + + +@pytest.mark.parametrize( + "transport_name", + [ + "rest", + ], +) +def test_generative_question_service_client_transport_session_collision(transport_name): + creds1 = ga_credentials.AnonymousCredentials() + creds2 = ga_credentials.AnonymousCredentials() + client1 = GenerativeQuestionServiceClient( + credentials=creds1, + transport=transport_name, + ) + client2 = GenerativeQuestionServiceClient( + credentials=creds2, + transport=transport_name, + ) + session1 = client1.transport.update_generative_questions_feature_config._session + session2 = client2.transport.update_generative_questions_feature_config._session + assert session1 != session2 + session1 = client1.transport.get_generative_questions_feature_config._session + session2 = client2.transport.get_generative_questions_feature_config._session + assert session1 != session2 + session1 = client1.transport.list_generative_question_configs._session + session2 = client2.transport.list_generative_question_configs._session + assert session1 != session2 + session1 = client1.transport.update_generative_question_config._session + session2 = client2.transport.update_generative_question_config._session + assert session1 != session2 + session1 = client1.transport.batch_update_generative_question_configs._session + session2 = client2.transport.batch_update_generative_question_configs._session + assert session1 != session2 + + +def test_generative_question_service_grpc_transport_channel(): + channel = grpc.secure_channel("http://localhost/", grpc.local_channel_credentials()) + + # Check that channel is used if provided. + transport = transports.GenerativeQuestionServiceGrpcTransport( + host="squid.clam.whelk", + channel=channel, + ) + assert transport.grpc_channel == channel + assert transport._host == "squid.clam.whelk:443" + assert transport._ssl_channel_credentials == None + + +def test_generative_question_service_grpc_asyncio_transport_channel(): + channel = aio.secure_channel("http://localhost/", grpc.local_channel_credentials()) + + # Check that channel is used if provided. + transport = transports.GenerativeQuestionServiceGrpcAsyncIOTransport( + host="squid.clam.whelk", + channel=channel, + ) + assert transport.grpc_channel == channel + assert transport._host == "squid.clam.whelk:443" + assert transport._ssl_channel_credentials == None + + +# Remove this test when deprecated arguments (api_mtls_endpoint, client_cert_source) are +# removed from grpc/grpc_asyncio transport constructor. +@pytest.mark.parametrize( + "transport_class", + [ + transports.GenerativeQuestionServiceGrpcTransport, + transports.GenerativeQuestionServiceGrpcAsyncIOTransport, + ], +) +def test_generative_question_service_transport_channel_mtls_with_client_cert_source( + transport_class, +): + with mock.patch( + "grpc.ssl_channel_credentials", autospec=True + ) as grpc_ssl_channel_cred: + with mock.patch.object( + transport_class, "create_channel" + ) as grpc_create_channel: + mock_ssl_cred = mock.Mock() + grpc_ssl_channel_cred.return_value = mock_ssl_cred + + mock_grpc_channel = mock.Mock() + grpc_create_channel.return_value = mock_grpc_channel + + cred = ga_credentials.AnonymousCredentials() + with pytest.warns(DeprecationWarning): + with mock.patch.object(google.auth, "default") as adc: + adc.return_value = (cred, None) + transport = transport_class( + host="squid.clam.whelk", + api_mtls_endpoint="mtls.squid.clam.whelk", + client_cert_source=client_cert_source_callback, + ) + adc.assert_called_once() + + grpc_ssl_channel_cred.assert_called_once_with( + certificate_chain=b"cert bytes", private_key=b"key bytes" + ) + grpc_create_channel.assert_called_once_with( + "mtls.squid.clam.whelk:443", + credentials=cred, + credentials_file=None, + scopes=None, + ssl_credentials=mock_ssl_cred, + quota_project_id=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + assert transport.grpc_channel == mock_grpc_channel + assert transport._ssl_channel_credentials == mock_ssl_cred + + +# Remove this test when deprecated arguments (api_mtls_endpoint, client_cert_source) are +# removed from grpc/grpc_asyncio transport constructor. +@pytest.mark.parametrize( + "transport_class", + [ + transports.GenerativeQuestionServiceGrpcTransport, + transports.GenerativeQuestionServiceGrpcAsyncIOTransport, + ], +) +def test_generative_question_service_transport_channel_mtls_with_adc(transport_class): + mock_ssl_cred = mock.Mock() + with mock.patch.multiple( + "google.auth.transport.grpc.SslCredentials", + __init__=mock.Mock(return_value=None), + ssl_credentials=mock.PropertyMock(return_value=mock_ssl_cred), + ): + with mock.patch.object( + transport_class, "create_channel" + ) as grpc_create_channel: + mock_grpc_channel = mock.Mock() + grpc_create_channel.return_value = mock_grpc_channel + mock_cred = mock.Mock() + + with pytest.warns(DeprecationWarning): + transport = transport_class( + host="squid.clam.whelk", + credentials=mock_cred, + api_mtls_endpoint="mtls.squid.clam.whelk", + client_cert_source=None, + ) + + grpc_create_channel.assert_called_once_with( + "mtls.squid.clam.whelk:443", + credentials=mock_cred, + credentials_file=None, + scopes=None, + ssl_credentials=mock_ssl_cred, + quota_project_id=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + assert transport.grpc_channel == mock_grpc_channel + + +def test_catalog_path(): + project = "squid" + location = "clam" + catalog = "whelk" + expected = "projects/{project}/locations/{location}/catalogs/{catalog}".format( + project=project, + location=location, + catalog=catalog, + ) + actual = GenerativeQuestionServiceClient.catalog_path(project, location, catalog) + assert expected == actual + + +def test_parse_catalog_path(): + expected = { + "project": "octopus", + "location": "oyster", + "catalog": "nudibranch", + } + path = GenerativeQuestionServiceClient.catalog_path(**expected) + + # Check that the path construction is reversible. + actual = GenerativeQuestionServiceClient.parse_catalog_path(path) + assert expected == actual + + +def test_common_billing_account_path(): + billing_account = "cuttlefish" + expected = "billingAccounts/{billing_account}".format( + billing_account=billing_account, + ) + actual = GenerativeQuestionServiceClient.common_billing_account_path( + billing_account + ) + assert expected == actual + + +def test_parse_common_billing_account_path(): + expected = { + "billing_account": "mussel", + } + path = GenerativeQuestionServiceClient.common_billing_account_path(**expected) + + # Check that the path construction is reversible. + actual = GenerativeQuestionServiceClient.parse_common_billing_account_path(path) + assert expected == actual + + +def test_common_folder_path(): + folder = "winkle" + expected = "folders/{folder}".format( + folder=folder, + ) + actual = GenerativeQuestionServiceClient.common_folder_path(folder) + assert expected == actual + + +def test_parse_common_folder_path(): + expected = { + "folder": "nautilus", + } + path = GenerativeQuestionServiceClient.common_folder_path(**expected) + + # Check that the path construction is reversible. + actual = GenerativeQuestionServiceClient.parse_common_folder_path(path) + assert expected == actual + + +def test_common_organization_path(): + organization = "scallop" + expected = "organizations/{organization}".format( + organization=organization, + ) + actual = GenerativeQuestionServiceClient.common_organization_path(organization) + assert expected == actual + + +def test_parse_common_organization_path(): + expected = { + "organization": "abalone", + } + path = GenerativeQuestionServiceClient.common_organization_path(**expected) + + # Check that the path construction is reversible. + actual = GenerativeQuestionServiceClient.parse_common_organization_path(path) + assert expected == actual + + +def test_common_project_path(): + project = "squid" + expected = "projects/{project}".format( + project=project, + ) + actual = GenerativeQuestionServiceClient.common_project_path(project) + assert expected == actual + + +def test_parse_common_project_path(): + expected = { + "project": "clam", + } + path = GenerativeQuestionServiceClient.common_project_path(**expected) + + # Check that the path construction is reversible. + actual = GenerativeQuestionServiceClient.parse_common_project_path(path) + assert expected == actual + + +def test_common_location_path(): + project = "whelk" + location = "octopus" + expected = "projects/{project}/locations/{location}".format( + project=project, + location=location, + ) + actual = GenerativeQuestionServiceClient.common_location_path(project, location) + assert expected == actual + + +def test_parse_common_location_path(): + expected = { + "project": "oyster", + "location": "nudibranch", + } + path = GenerativeQuestionServiceClient.common_location_path(**expected) + + # Check that the path construction is reversible. + actual = GenerativeQuestionServiceClient.parse_common_location_path(path) + assert expected == actual + + +def test_client_with_default_client_info(): + client_info = gapic_v1.client_info.ClientInfo() + + with mock.patch.object( + transports.GenerativeQuestionServiceTransport, "_prep_wrapped_messages" + ) as prep: + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + client_info=client_info, + ) + prep.assert_called_once_with(client_info) + + with mock.patch.object( + transports.GenerativeQuestionServiceTransport, "_prep_wrapped_messages" + ) as prep: + transport_class = GenerativeQuestionServiceClient.get_transport_class() + transport = transport_class( + credentials=ga_credentials.AnonymousCredentials(), + client_info=client_info, + ) + prep.assert_called_once_with(client_info) + + +@pytest.mark.asyncio +async def test_transport_close_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + with mock.patch.object( + type(getattr(client.transport, "grpc_channel")), "close" + ) as close: + async with client: + close.assert_not_called() + close.assert_called_once() + + +def test_get_operation_rest_bad_request( + transport: str = "rest", request_type=operations_pb2.GetOperationRequest +): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + request = request_type() + request = json_format.ParseDict( + { + "name": "projects/sample1/locations/sample2/catalogs/sample3/branches/sample4/operations/sample5" + }, + request, + ) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 400 + response_value.request = Request() + req.return_value = response_value + client.get_operation(request) + + +@pytest.mark.parametrize( + "request_type", + [ + operations_pb2.GetOperationRequest, + dict, + ], +) +def test_get_operation_rest(request_type): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request_init = { + "name": "projects/sample1/locations/sample2/catalogs/sample3/branches/sample4/operations/sample5" + } + request = request_type(**request_init) + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = operations_pb2.Operation() + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + response = client.get_operation(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, operations_pb2.Operation) + + +def test_list_operations_rest_bad_request( + transport: str = "rest", request_type=operations_pb2.ListOperationsRequest +): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + request = request_type() + request = json_format.ParseDict( + {"name": "projects/sample1/locations/sample2/catalogs/sample3"}, request + ) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 400 + response_value.request = Request() + req.return_value = response_value + client.list_operations(request) + + +@pytest.mark.parametrize( + "request_type", + [ + operations_pb2.ListOperationsRequest, + dict, + ], +) +def test_list_operations_rest(request_type): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request_init = {"name": "projects/sample1/locations/sample2/catalogs/sample3"} + request = request_type(**request_init) + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = operations_pb2.ListOperationsResponse() + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + response = client.list_operations(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, operations_pb2.ListOperationsResponse) + + +def test_get_operation(transport: str = "grpc"): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = operations_pb2.GetOperationRequest() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_operation), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.Operation() + response = client.get_operation(request) + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, operations_pb2.Operation) + + +@pytest.mark.asyncio +async def test_get_operation_async(transport: str = "grpc_asyncio"): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = operations_pb2.GetOperationRequest() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_operation), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation() + ) + response = await client.get_operation(request) + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, operations_pb2.Operation) + + +def test_get_operation_field_headers(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = operations_pb2.GetOperationRequest() + request.name = "locations" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_operation), "__call__") as call: + call.return_value = operations_pb2.Operation() + + client.get_operation(request) + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "name=locations", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_get_operation_field_headers_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = operations_pb2.GetOperationRequest() + request.name = "locations" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_operation), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation() + ) + await client.get_operation(request) + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "name=locations", + ) in kw["metadata"] + + +def test_get_operation_from_dict(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_operation), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.Operation() + + response = client.get_operation( + request={ + "name": "locations", + } + ) + call.assert_called() + + +@pytest.mark.asyncio +async def test_get_operation_from_dict_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_operation), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation() + ) + response = await client.get_operation( + request={ + "name": "locations", + } + ) + call.assert_called() + + +def test_list_operations(transport: str = "grpc"): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = operations_pb2.ListOperationsRequest() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_operations), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.ListOperationsResponse() + response = client.list_operations(request) + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, operations_pb2.ListOperationsResponse) + + +@pytest.mark.asyncio +async def test_list_operations_async(transport: str = "grpc_asyncio"): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = operations_pb2.ListOperationsRequest() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_operations), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.ListOperationsResponse() + ) + response = await client.list_operations(request) + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, operations_pb2.ListOperationsResponse) + + +def test_list_operations_field_headers(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = operations_pb2.ListOperationsRequest() + request.name = "locations" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_operations), "__call__") as call: + call.return_value = operations_pb2.ListOperationsResponse() + + client.list_operations(request) + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "name=locations", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_list_operations_field_headers_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = operations_pb2.ListOperationsRequest() + request.name = "locations" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_operations), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.ListOperationsResponse() + ) + await client.list_operations(request) + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "name=locations", + ) in kw["metadata"] + + +def test_list_operations_from_dict(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_operations), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.ListOperationsResponse() + + response = client.list_operations( + request={ + "name": "locations", + } + ) + call.assert_called() + + +@pytest.mark.asyncio +async def test_list_operations_from_dict_async(): + client = GenerativeQuestionServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_operations), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.ListOperationsResponse() + ) + response = await client.list_operations( + request={ + "name": "locations", + } + ) + call.assert_called() + + +def test_transport_close(): + transports = { + "rest": "_session", + "grpc": "_grpc_channel", + } + + for transport, close_name in transports.items(): + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + with mock.patch.object( + type(getattr(client.transport, close_name)), "close" + ) as close: + with client: + close.assert_not_called() + close.assert_called_once() + + +def test_client_ctx(): + transports = [ + "rest", + "grpc", + ] + for transport in transports: + client = GenerativeQuestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + # Test client calls underlying transport. + with mock.patch.object(type(client.transport), "close") as close: + close.assert_not_called() + with client: + pass + close.assert_called() + + +@pytest.mark.parametrize( + "client_class,transport_class", + [ + ( + GenerativeQuestionServiceClient, + transports.GenerativeQuestionServiceGrpcTransport, + ), + ( + GenerativeQuestionServiceAsyncClient, + transports.GenerativeQuestionServiceGrpcAsyncIOTransport, + ), + ], +) +def test_api_key_credentials(client_class, transport_class): + with mock.patch.object( + google.auth._default, "get_api_key_credentials", create=True + ) as get_api_key_credentials: + mock_cred = mock.Mock() + get_api_key_credentials.return_value = mock_cred + options = client_options.ClientOptions() + options.api_key = "api_key" + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options) + patched.assert_called_once_with( + credentials=mock_cred, + credentials_file=None, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) diff --git a/packages/google-cloud-retail/tests/unit/gapic/retail_v2beta/test_product_service.py b/packages/google-cloud-retail/tests/unit/gapic/retail_v2beta/test_product_service.py index 179b69104960..a257812e39fe 100644 --- a/packages/google-cloud-retail/tests/unit/gapic/retail_v2beta/test_product_service.py +++ b/packages/google-cloud-retail/tests/unit/gapic/retail_v2beta/test_product_service.py @@ -65,8 +65,8 @@ pagers, transports, ) +from google.cloud.retail_v2beta.types import common, export_config, import_config from google.cloud.retail_v2beta.types import product_service, promotion, purge_config -from google.cloud.retail_v2beta.types import common, import_config from google.cloud.retail_v2beta.types import product from google.cloud.retail_v2beta.types import product as gcr_product @@ -4006,6 +4006,293 @@ async def test_import_products_field_headers_async(): ) in kw["metadata"] +@pytest.mark.parametrize( + "request_type", + [ + export_config.ExportProductsRequest, + dict, + ], +) +def test_export_products(request_type, transport: str = "grpc"): + client = ProductServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.export_products), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.Operation(name="operations/spam") + response = client.export_products(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = export_config.ExportProductsRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, future.Future) + + +def test_export_products_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = ProductServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.export_products), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.export_products() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == export_config.ExportProductsRequest() + + +def test_export_products_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = ProductServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = export_config.ExportProductsRequest( + parent="parent_value", + filter="filter_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.export_products), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.export_products(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == export_config.ExportProductsRequest( + parent="parent_value", + filter="filter_value", + ) + + +def test_export_products_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = ProductServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.export_products in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.export_products] = mock_rpc + request = {} + client.export_products(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + # Operation methods call wrapper_fn to build a cached + # client._transport.operations_client instance on first rpc call. + # Subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + client.export_products(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_export_products_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = ProductServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.export_products), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/spam") + ) + response = await client.export_products() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == export_config.ExportProductsRequest() + + +@pytest.mark.asyncio +async def test_export_products_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = ProductServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.export_products + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.AsyncMock() + mock_rpc.return_value = mock.Mock() + client._client._transport._wrapped_methods[ + client._client._transport.export_products + ] = mock_rpc + + request = {} + await client.export_products(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + # Operation methods call wrapper_fn to build a cached + # client._transport.operations_client instance on first rpc call. + # Subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + await client.export_products(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_export_products_async( + transport: str = "grpc_asyncio", request_type=export_config.ExportProductsRequest +): + client = ProductServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.export_products), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/spam") + ) + response = await client.export_products(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = export_config.ExportProductsRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, future.Future) + + +@pytest.mark.asyncio +async def test_export_products_async_from_dict(): + await test_export_products_async(request_type=dict) + + +def test_export_products_field_headers(): + client = ProductServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = export_config.ExportProductsRequest() + + request.parent = "parent_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.export_products), "__call__") as call: + call.return_value = operations_pb2.Operation(name="operations/op") + client.export_products(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "parent=parent_value", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_export_products_field_headers_async(): + client = ProductServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = export_config.ExportProductsRequest() + + request.parent = "parent_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.export_products), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/op") + ) + await client.export_products(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "parent=parent_value", + ) in kw["metadata"] + + @pytest.mark.parametrize( "request_type", [ @@ -8516,6 +8803,263 @@ def test_import_products_rest_error(): ) +@pytest.mark.parametrize( + "request_type", + [ + export_config.ExportProductsRequest, + dict, + ], +) +def test_export_products_rest(request_type): + client = ProductServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = { + "parent": "projects/sample1/locations/sample2/catalogs/sample3/branches/sample4" + } + request = request_type(**request_init) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = operations_pb2.Operation(name="operations/spam") + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + response = client.export_products(request) + + # Establish that the response is the type that we expect. + assert response.operation.name == "operations/spam" + + +def test_export_products_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = ProductServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.export_products in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.export_products] = mock_rpc + + request = {} + client.export_products(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + # Operation methods build a cached wrapper on first rpc call + # subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + client.export_products(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_export_products_rest_required_fields( + request_type=export_config.ExportProductsRequest, +): + transport_class = transports.ProductServiceRestTransport + + request_init = {} + request_init["parent"] = "" + request = request_type(**request_init) + pb_request = request_type.pb(request) + jsonified_request = json.loads( + json_format.MessageToJson(pb_request, use_integers_for_enums=False) + ) + + # verify fields with default values are dropped + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).export_products._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + jsonified_request["parent"] = "parent_value" + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).export_products._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + assert "parent" in jsonified_request + assert jsonified_request["parent"] == "parent_value" + + client = ProductServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = operations_pb2.Operation(name="operations/spam") + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # We need to mock transcode() because providing default values + # for required fields will fail the real version if the http_options + # expect actual values for those fields. + with mock.patch.object(path_template, "transcode") as transcode: + # A uri without fields and an empty body will force all the + # request fields to show up in the query_params. + pb_request = request_type.pb(request) + transcode_result = { + "uri": "v1/sample_method", + "method": "post", + "query_params": pb_request, + } + transcode_result["body"] = pb_request + transcode.return_value = transcode_result + + response_value = Response() + response_value.status_code = 200 + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + response = client.export_products(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_export_products_rest_unset_required_fields(): + transport = transports.ProductServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.export_products._get_unset_required_fields({}) + assert set(unset_fields) == ( + set(()) + & set( + ( + "parent", + "outputConfig", + ) + ) + ) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_export_products_rest_interceptors(null_interceptor): + transport = transports.ProductServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.ProductServiceRestInterceptor(), + ) + client = ProductServiceClient(transport=transport) + with mock.patch.object( + type(client.transport._session), "request" + ) as req, mock.patch.object( + path_template, "transcode" + ) as transcode, mock.patch.object( + operation.Operation, "_set_result_from_operation" + ), mock.patch.object( + transports.ProductServiceRestInterceptor, "post_export_products" + ) as post, mock.patch.object( + transports.ProductServiceRestInterceptor, "pre_export_products" + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = export_config.ExportProductsRequest.pb( + export_config.ExportProductsRequest() + ) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = Response() + req.return_value.status_code = 200 + req.return_value.request = PreparedRequest() + req.return_value._content = json_format.MessageToJson( + operations_pb2.Operation() + ) + + request = export_config.ExportProductsRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = operations_pb2.Operation() + + client.export_products( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_export_products_rest_bad_request( + transport: str = "rest", request_type=export_config.ExportProductsRequest +): + client = ProductServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = { + "parent": "projects/sample1/locations/sample2/catalogs/sample3/branches/sample4" + } + request = request_type(**request_init) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 400 + response_value.request = Request() + req.return_value = response_value + client.export_products(request) + + +def test_export_products_rest_error(): + client = ProductServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + @pytest.mark.parametrize( "request_type", [ @@ -10269,6 +10813,7 @@ def test_product_service_base_transport(): "delete_product", "purge_products", "import_products", + "export_products", "set_inventory", "add_fulfillment_places", "remove_fulfillment_places", @@ -10577,6 +11122,9 @@ def test_product_service_client_transport_session_collision(transport_name): session1 = client1.transport.import_products._session session2 = client2.transport.import_products._session assert session1 != session2 + session1 = client1.transport.export_products._session + session2 = client2.transport.export_products._session + assert session1 != session2 session1 = client1.transport.set_inventory._session session2 = client2.transport.set_inventory._session assert session1 != session2 diff --git a/packages/google-cloud-retail/tests/unit/gapic/retail_v2beta/test_project_service.py b/packages/google-cloud-retail/tests/unit/gapic/retail_v2beta/test_project_service.py new file mode 100644 index 000000000000..af942ae80891 --- /dev/null +++ b/packages/google-cloud-retail/tests/unit/gapic/retail_v2beta/test_project_service.py @@ -0,0 +1,3729 @@ +# -*- coding: utf-8 -*- +# Copyright 2024 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +import os + +# try/except added for compatibility with python < 3.8 +try: + from unittest import mock + from unittest.mock import AsyncMock # pragma: NO COVER +except ImportError: # pragma: NO COVER + import mock + +from collections.abc import Iterable +import json +import math + +from google.api_core import gapic_v1, grpc_helpers, grpc_helpers_async, path_template +from google.api_core import api_core_version, client_options +from google.api_core import exceptions as core_exceptions +from google.api_core import retry as retries +import google.auth +from google.auth import credentials as ga_credentials +from google.auth.exceptions import MutualTLSChannelError +from google.cloud.location import locations_pb2 +from google.longrunning import operations_pb2 # type: ignore +from google.oauth2 import service_account +from google.protobuf import field_mask_pb2 # type: ignore +from google.protobuf import json_format +import grpc +from grpc.experimental import aio +from proto.marshal.rules import wrappers +from proto.marshal.rules.dates import DurationRule, TimestampRule +import pytest +from requests import PreparedRequest, Request, Response +from requests.sessions import Session + +from google.cloud.retail_v2beta.services.project_service import ( + ProjectServiceAsyncClient, + ProjectServiceClient, + transports, +) +from google.cloud.retail_v2beta.types import project, project_service + + +def client_cert_source_callback(): + return b"cert bytes", b"key bytes" + + +# If default endpoint is localhost, then default mtls endpoint will be the same. +# This method modifies the default endpoint so the client can produce a different +# mtls endpoint for endpoint testing purposes. +def modify_default_endpoint(client): + return ( + "foo.googleapis.com" + if ("localhost" in client.DEFAULT_ENDPOINT) + else client.DEFAULT_ENDPOINT + ) + + +# If default endpoint template is localhost, then default mtls endpoint will be the same. +# This method modifies the default endpoint template so the client can produce a different +# mtls endpoint for endpoint testing purposes. +def modify_default_endpoint_template(client): + return ( + "test.{UNIVERSE_DOMAIN}" + if ("localhost" in client._DEFAULT_ENDPOINT_TEMPLATE) + else client._DEFAULT_ENDPOINT_TEMPLATE + ) + + +def test__get_default_mtls_endpoint(): + api_endpoint = "example.googleapis.com" + api_mtls_endpoint = "example.mtls.googleapis.com" + sandbox_endpoint = "example.sandbox.googleapis.com" + sandbox_mtls_endpoint = "example.mtls.sandbox.googleapis.com" + non_googleapi = "api.example.com" + + assert ProjectServiceClient._get_default_mtls_endpoint(None) is None + assert ( + ProjectServiceClient._get_default_mtls_endpoint(api_endpoint) + == api_mtls_endpoint + ) + assert ( + ProjectServiceClient._get_default_mtls_endpoint(api_mtls_endpoint) + == api_mtls_endpoint + ) + assert ( + ProjectServiceClient._get_default_mtls_endpoint(sandbox_endpoint) + == sandbox_mtls_endpoint + ) + assert ( + ProjectServiceClient._get_default_mtls_endpoint(sandbox_mtls_endpoint) + == sandbox_mtls_endpoint + ) + assert ( + ProjectServiceClient._get_default_mtls_endpoint(non_googleapi) == non_googleapi + ) + + +def test__read_environment_variables(): + assert ProjectServiceClient._read_environment_variables() == (False, "auto", None) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "true"}): + assert ProjectServiceClient._read_environment_variables() == ( + True, + "auto", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "false"}): + assert ProjectServiceClient._read_environment_variables() == ( + False, + "auto", + None, + ) + + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"} + ): + with pytest.raises(ValueError) as excinfo: + ProjectServiceClient._read_environment_variables() + assert ( + str(excinfo.value) + == "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): + assert ProjectServiceClient._read_environment_variables() == ( + False, + "never", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): + assert ProjectServiceClient._read_environment_variables() == ( + False, + "always", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "auto"}): + assert ProjectServiceClient._read_environment_variables() == ( + False, + "auto", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "Unsupported"}): + with pytest.raises(MutualTLSChannelError) as excinfo: + ProjectServiceClient._read_environment_variables() + assert ( + str(excinfo.value) + == "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`" + ) + + with mock.patch.dict(os.environ, {"GOOGLE_CLOUD_UNIVERSE_DOMAIN": "foo.com"}): + assert ProjectServiceClient._read_environment_variables() == ( + False, + "auto", + "foo.com", + ) + + +def test__get_client_cert_source(): + mock_provided_cert_source = mock.Mock() + mock_default_cert_source = mock.Mock() + + assert ProjectServiceClient._get_client_cert_source(None, False) is None + assert ( + ProjectServiceClient._get_client_cert_source(mock_provided_cert_source, False) + is None + ) + assert ( + ProjectServiceClient._get_client_cert_source(mock_provided_cert_source, True) + == mock_provided_cert_source + ) + + with mock.patch( + "google.auth.transport.mtls.has_default_client_cert_source", return_value=True + ): + with mock.patch( + "google.auth.transport.mtls.default_client_cert_source", + return_value=mock_default_cert_source, + ): + assert ( + ProjectServiceClient._get_client_cert_source(None, True) + is mock_default_cert_source + ) + assert ( + ProjectServiceClient._get_client_cert_source( + mock_provided_cert_source, "true" + ) + is mock_provided_cert_source + ) + + +@mock.patch.object( + ProjectServiceClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(ProjectServiceClient), +) +@mock.patch.object( + ProjectServiceAsyncClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(ProjectServiceAsyncClient), +) +def test__get_api_endpoint(): + api_override = "foo.com" + mock_client_cert_source = mock.Mock() + default_universe = ProjectServiceClient._DEFAULT_UNIVERSE + default_endpoint = ProjectServiceClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=default_universe + ) + mock_universe = "bar.com" + mock_endpoint = ProjectServiceClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=mock_universe + ) + + assert ( + ProjectServiceClient._get_api_endpoint( + api_override, mock_client_cert_source, default_universe, "always" + ) + == api_override + ) + assert ( + ProjectServiceClient._get_api_endpoint( + None, mock_client_cert_source, default_universe, "auto" + ) + == ProjectServiceClient.DEFAULT_MTLS_ENDPOINT + ) + assert ( + ProjectServiceClient._get_api_endpoint(None, None, default_universe, "auto") + == default_endpoint + ) + assert ( + ProjectServiceClient._get_api_endpoint(None, None, default_universe, "always") + == ProjectServiceClient.DEFAULT_MTLS_ENDPOINT + ) + assert ( + ProjectServiceClient._get_api_endpoint( + None, mock_client_cert_source, default_universe, "always" + ) + == ProjectServiceClient.DEFAULT_MTLS_ENDPOINT + ) + assert ( + ProjectServiceClient._get_api_endpoint(None, None, mock_universe, "never") + == mock_endpoint + ) + assert ( + ProjectServiceClient._get_api_endpoint(None, None, default_universe, "never") + == default_endpoint + ) + + with pytest.raises(MutualTLSChannelError) as excinfo: + ProjectServiceClient._get_api_endpoint( + None, mock_client_cert_source, mock_universe, "auto" + ) + assert ( + str(excinfo.value) + == "mTLS is not supported in any universe other than googleapis.com." + ) + + +def test__get_universe_domain(): + client_universe_domain = "foo.com" + universe_domain_env = "bar.com" + + assert ( + ProjectServiceClient._get_universe_domain( + client_universe_domain, universe_domain_env + ) + == client_universe_domain + ) + assert ( + ProjectServiceClient._get_universe_domain(None, universe_domain_env) + == universe_domain_env + ) + assert ( + ProjectServiceClient._get_universe_domain(None, None) + == ProjectServiceClient._DEFAULT_UNIVERSE + ) + + with pytest.raises(ValueError) as excinfo: + ProjectServiceClient._get_universe_domain("", None) + assert str(excinfo.value) == "Universe Domain cannot be an empty string." + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name", + [ + (ProjectServiceClient, transports.ProjectServiceGrpcTransport, "grpc"), + (ProjectServiceClient, transports.ProjectServiceRestTransport, "rest"), + ], +) +def test__validate_universe_domain(client_class, transport_class, transport_name): + client = client_class( + transport=transport_class(credentials=ga_credentials.AnonymousCredentials()) + ) + assert client._validate_universe_domain() == True + + # Test the case when universe is already validated. + assert client._validate_universe_domain() == True + + if transport_name == "grpc": + # Test the case where credentials are provided by the + # `local_channel_credentials`. The default universes in both match. + channel = grpc.secure_channel( + "http://localhost/", grpc.local_channel_credentials() + ) + client = client_class(transport=transport_class(channel=channel)) + assert client._validate_universe_domain() == True + + # Test the case where credentials do not exist: e.g. a transport is provided + # with no credentials. Validation should still succeed because there is no + # mismatch with non-existent credentials. + channel = grpc.secure_channel( + "http://localhost/", grpc.local_channel_credentials() + ) + transport = transport_class(channel=channel) + transport._credentials = None + client = client_class(transport=transport) + assert client._validate_universe_domain() == True + + # TODO: This is needed to cater for older versions of google-auth + # Make this test unconditional once the minimum supported version of + # google-auth becomes 2.23.0 or higher. + google_auth_major, google_auth_minor = [ + int(part) for part in google.auth.__version__.split(".")[0:2] + ] + if google_auth_major > 2 or (google_auth_major == 2 and google_auth_minor >= 23): + credentials = ga_credentials.AnonymousCredentials() + credentials._universe_domain = "foo.com" + # Test the case when there is a universe mismatch from the credentials. + client = client_class(transport=transport_class(credentials=credentials)) + with pytest.raises(ValueError) as excinfo: + client._validate_universe_domain() + assert ( + str(excinfo.value) + == "The configured universe domain (googleapis.com) does not match the universe domain found in the credentials (foo.com). If you haven't configured the universe domain explicitly, `googleapis.com` is the default." + ) + + # Test the case when there is a universe mismatch from the client. + # + # TODO: Make this test unconditional once the minimum supported version of + # google-api-core becomes 2.15.0 or higher. + api_core_major, api_core_minor = [ + int(part) for part in api_core_version.__version__.split(".")[0:2] + ] + if api_core_major > 2 or (api_core_major == 2 and api_core_minor >= 15): + client = client_class( + client_options={"universe_domain": "bar.com"}, + transport=transport_class( + credentials=ga_credentials.AnonymousCredentials(), + ), + ) + with pytest.raises(ValueError) as excinfo: + client._validate_universe_domain() + assert ( + str(excinfo.value) + == "The configured universe domain (bar.com) does not match the universe domain found in the credentials (googleapis.com). If you haven't configured the universe domain explicitly, `googleapis.com` is the default." + ) + + # Test that ValueError is raised if universe_domain is provided via client options and credentials is None + with pytest.raises(ValueError): + client._compare_universes("foo.bar", None) + + +@pytest.mark.parametrize( + "client_class,transport_name", + [ + (ProjectServiceClient, "grpc"), + (ProjectServiceAsyncClient, "grpc_asyncio"), + (ProjectServiceClient, "rest"), + ], +) +def test_project_service_client_from_service_account_info(client_class, transport_name): + creds = ga_credentials.AnonymousCredentials() + with mock.patch.object( + service_account.Credentials, "from_service_account_info" + ) as factory: + factory.return_value = creds + info = {"valid": True} + client = client_class.from_service_account_info(info, transport=transport_name) + assert client.transport._credentials == creds + assert isinstance(client, client_class) + + assert client.transport._host == ( + "retail.googleapis.com:443" + if transport_name in ["grpc", "grpc_asyncio"] + else "https://retail.googleapis.com" + ) + + +@pytest.mark.parametrize( + "transport_class,transport_name", + [ + (transports.ProjectServiceGrpcTransport, "grpc"), + (transports.ProjectServiceGrpcAsyncIOTransport, "grpc_asyncio"), + (transports.ProjectServiceRestTransport, "rest"), + ], +) +def test_project_service_client_service_account_always_use_jwt( + transport_class, transport_name +): + with mock.patch.object( + service_account.Credentials, "with_always_use_jwt_access", create=True + ) as use_jwt: + creds = service_account.Credentials(None, None, None) + transport = transport_class(credentials=creds, always_use_jwt_access=True) + use_jwt.assert_called_once_with(True) + + with mock.patch.object( + service_account.Credentials, "with_always_use_jwt_access", create=True + ) as use_jwt: + creds = service_account.Credentials(None, None, None) + transport = transport_class(credentials=creds, always_use_jwt_access=False) + use_jwt.assert_not_called() + + +@pytest.mark.parametrize( + "client_class,transport_name", + [ + (ProjectServiceClient, "grpc"), + (ProjectServiceAsyncClient, "grpc_asyncio"), + (ProjectServiceClient, "rest"), + ], +) +def test_project_service_client_from_service_account_file(client_class, transport_name): + creds = ga_credentials.AnonymousCredentials() + with mock.patch.object( + service_account.Credentials, "from_service_account_file" + ) as factory: + factory.return_value = creds + client = client_class.from_service_account_file( + "dummy/file/path.json", transport=transport_name + ) + assert client.transport._credentials == creds + assert isinstance(client, client_class) + + client = client_class.from_service_account_json( + "dummy/file/path.json", transport=transport_name + ) + assert client.transport._credentials == creds + assert isinstance(client, client_class) + + assert client.transport._host == ( + "retail.googleapis.com:443" + if transport_name in ["grpc", "grpc_asyncio"] + else "https://retail.googleapis.com" + ) + + +def test_project_service_client_get_transport_class(): + transport = ProjectServiceClient.get_transport_class() + available_transports = [ + transports.ProjectServiceGrpcTransport, + transports.ProjectServiceRestTransport, + ] + assert transport in available_transports + + transport = ProjectServiceClient.get_transport_class("grpc") + assert transport == transports.ProjectServiceGrpcTransport + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name", + [ + (ProjectServiceClient, transports.ProjectServiceGrpcTransport, "grpc"), + ( + ProjectServiceAsyncClient, + transports.ProjectServiceGrpcAsyncIOTransport, + "grpc_asyncio", + ), + (ProjectServiceClient, transports.ProjectServiceRestTransport, "rest"), + ], +) +@mock.patch.object( + ProjectServiceClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(ProjectServiceClient), +) +@mock.patch.object( + ProjectServiceAsyncClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(ProjectServiceAsyncClient), +) +def test_project_service_client_client_options( + client_class, transport_class, transport_name +): + # Check that if channel is provided we won't create a new one. + with mock.patch.object(ProjectServiceClient, "get_transport_class") as gtc: + transport = transport_class(credentials=ga_credentials.AnonymousCredentials()) + client = client_class(transport=transport) + gtc.assert_not_called() + + # Check that if channel is provided via str we will create a new one. + with mock.patch.object(ProjectServiceClient, "get_transport_class") as gtc: + client = client_class(transport=transport_name) + gtc.assert_called() + + # Check the case api_endpoint is provided. + options = client_options.ClientOptions(api_endpoint="squid.clam.whelk") + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(transport=transport_name, client_options=options) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host="squid.clam.whelk", + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT is + # "never". + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT is + # "always". + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client.DEFAULT_MTLS_ENDPOINT, + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT has + # unsupported value. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "Unsupported"}): + with pytest.raises(MutualTLSChannelError) as excinfo: + client = client_class(transport=transport_name) + assert ( + str(excinfo.value) + == "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`" + ) + + # Check the case GOOGLE_API_USE_CLIENT_CERTIFICATE has unsupported value. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"} + ): + with pytest.raises(ValueError) as excinfo: + client = client_class(transport=transport_name) + assert ( + str(excinfo.value) + == "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + + # Check the case quota_project_id is provided + options = client_options.ClientOptions(quota_project_id="octopus") + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options, transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id="octopus", + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + # Check the case api_endpoint is provided + options = client_options.ClientOptions( + api_audience="https://language.googleapis.com" + ) + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options, transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience="https://language.googleapis.com", + ) + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name,use_client_cert_env", + [ + (ProjectServiceClient, transports.ProjectServiceGrpcTransport, "grpc", "true"), + ( + ProjectServiceAsyncClient, + transports.ProjectServiceGrpcAsyncIOTransport, + "grpc_asyncio", + "true", + ), + (ProjectServiceClient, transports.ProjectServiceGrpcTransport, "grpc", "false"), + ( + ProjectServiceAsyncClient, + transports.ProjectServiceGrpcAsyncIOTransport, + "grpc_asyncio", + "false", + ), + (ProjectServiceClient, transports.ProjectServiceRestTransport, "rest", "true"), + (ProjectServiceClient, transports.ProjectServiceRestTransport, "rest", "false"), + ], +) +@mock.patch.object( + ProjectServiceClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(ProjectServiceClient), +) +@mock.patch.object( + ProjectServiceAsyncClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(ProjectServiceAsyncClient), +) +@mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "auto"}) +def test_project_service_client_mtls_env_auto( + client_class, transport_class, transport_name, use_client_cert_env +): + # This tests the endpoint autoswitch behavior. Endpoint is autoswitched to the default + # mtls endpoint, if GOOGLE_API_USE_CLIENT_CERTIFICATE is "true" and client cert exists. + + # Check the case client_cert_source is provided. Whether client cert is used depends on + # GOOGLE_API_USE_CLIENT_CERTIFICATE value. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": use_client_cert_env} + ): + options = client_options.ClientOptions( + client_cert_source=client_cert_source_callback + ) + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options, transport=transport_name) + + if use_client_cert_env == "false": + expected_client_cert_source = None + expected_host = client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ) + else: + expected_client_cert_source = client_cert_source_callback + expected_host = client.DEFAULT_MTLS_ENDPOINT + + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=expected_host, + scopes=None, + client_cert_source_for_mtls=expected_client_cert_source, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + # Check the case ADC client cert is provided. Whether client cert is used depends on + # GOOGLE_API_USE_CLIENT_CERTIFICATE value. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": use_client_cert_env} + ): + with mock.patch.object(transport_class, "__init__") as patched: + with mock.patch( + "google.auth.transport.mtls.has_default_client_cert_source", + return_value=True, + ): + with mock.patch( + "google.auth.transport.mtls.default_client_cert_source", + return_value=client_cert_source_callback, + ): + if use_client_cert_env == "false": + expected_host = client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ) + expected_client_cert_source = None + else: + expected_host = client.DEFAULT_MTLS_ENDPOINT + expected_client_cert_source = client_cert_source_callback + + patched.return_value = None + client = client_class(transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=expected_host, + scopes=None, + client_cert_source_for_mtls=expected_client_cert_source, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + # Check the case client_cert_source and ADC client cert are not provided. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": use_client_cert_env} + ): + with mock.patch.object(transport_class, "__init__") as patched: + with mock.patch( + "google.auth.transport.mtls.has_default_client_cert_source", + return_value=False, + ): + patched.return_value = None + client = client_class(transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + +@pytest.mark.parametrize( + "client_class", [ProjectServiceClient, ProjectServiceAsyncClient] +) +@mock.patch.object( + ProjectServiceClient, + "DEFAULT_ENDPOINT", + modify_default_endpoint(ProjectServiceClient), +) +@mock.patch.object( + ProjectServiceAsyncClient, + "DEFAULT_ENDPOINT", + modify_default_endpoint(ProjectServiceAsyncClient), +) +def test_project_service_client_get_mtls_endpoint_and_cert_source(client_class): + mock_client_cert_source = mock.Mock() + + # Test the case GOOGLE_API_USE_CLIENT_CERTIFICATE is "true". + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "true"}): + mock_api_endpoint = "foo" + options = client_options.ClientOptions( + client_cert_source=mock_client_cert_source, api_endpoint=mock_api_endpoint + ) + api_endpoint, cert_source = client_class.get_mtls_endpoint_and_cert_source( + options + ) + assert api_endpoint == mock_api_endpoint + assert cert_source == mock_client_cert_source + + # Test the case GOOGLE_API_USE_CLIENT_CERTIFICATE is "false". + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "false"}): + mock_client_cert_source = mock.Mock() + mock_api_endpoint = "foo" + options = client_options.ClientOptions( + client_cert_source=mock_client_cert_source, api_endpoint=mock_api_endpoint + ) + api_endpoint, cert_source = client_class.get_mtls_endpoint_and_cert_source( + options + ) + assert api_endpoint == mock_api_endpoint + assert cert_source is None + + # Test the case GOOGLE_API_USE_MTLS_ENDPOINT is "never". + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): + api_endpoint, cert_source = client_class.get_mtls_endpoint_and_cert_source() + assert api_endpoint == client_class.DEFAULT_ENDPOINT + assert cert_source is None + + # Test the case GOOGLE_API_USE_MTLS_ENDPOINT is "always". + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): + api_endpoint, cert_source = client_class.get_mtls_endpoint_and_cert_source() + assert api_endpoint == client_class.DEFAULT_MTLS_ENDPOINT + assert cert_source is None + + # Test the case GOOGLE_API_USE_MTLS_ENDPOINT is "auto" and default cert doesn't exist. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "true"}): + with mock.patch( + "google.auth.transport.mtls.has_default_client_cert_source", + return_value=False, + ): + api_endpoint, cert_source = client_class.get_mtls_endpoint_and_cert_source() + assert api_endpoint == client_class.DEFAULT_ENDPOINT + assert cert_source is None + + # Test the case GOOGLE_API_USE_MTLS_ENDPOINT is "auto" and default cert exists. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "true"}): + with mock.patch( + "google.auth.transport.mtls.has_default_client_cert_source", + return_value=True, + ): + with mock.patch( + "google.auth.transport.mtls.default_client_cert_source", + return_value=mock_client_cert_source, + ): + ( + api_endpoint, + cert_source, + ) = client_class.get_mtls_endpoint_and_cert_source() + assert api_endpoint == client_class.DEFAULT_MTLS_ENDPOINT + assert cert_source == mock_client_cert_source + + # Check the case api_endpoint is not provided and GOOGLE_API_USE_MTLS_ENDPOINT has + # unsupported value. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "Unsupported"}): + with pytest.raises(MutualTLSChannelError) as excinfo: + client_class.get_mtls_endpoint_and_cert_source() + + assert ( + str(excinfo.value) + == "Environment variable `GOOGLE_API_USE_MTLS_ENDPOINT` must be `never`, `auto` or `always`" + ) + + # Check the case GOOGLE_API_USE_CLIENT_CERTIFICATE has unsupported value. + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"} + ): + with pytest.raises(ValueError) as excinfo: + client_class.get_mtls_endpoint_and_cert_source() + + assert ( + str(excinfo.value) + == "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + + +@pytest.mark.parametrize( + "client_class", [ProjectServiceClient, ProjectServiceAsyncClient] +) +@mock.patch.object( + ProjectServiceClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(ProjectServiceClient), +) +@mock.patch.object( + ProjectServiceAsyncClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(ProjectServiceAsyncClient), +) +def test_project_service_client_client_api_endpoint(client_class): + mock_client_cert_source = client_cert_source_callback + api_override = "foo.com" + default_universe = ProjectServiceClient._DEFAULT_UNIVERSE + default_endpoint = ProjectServiceClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=default_universe + ) + mock_universe = "bar.com" + mock_endpoint = ProjectServiceClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=mock_universe + ) + + # If ClientOptions.api_endpoint is set and GOOGLE_API_USE_CLIENT_CERTIFICATE="true", + # use ClientOptions.api_endpoint as the api endpoint regardless. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "true"}): + with mock.patch( + "google.auth.transport.requests.AuthorizedSession.configure_mtls_channel" + ): + options = client_options.ClientOptions( + client_cert_source=mock_client_cert_source, api_endpoint=api_override + ) + client = client_class( + client_options=options, + credentials=ga_credentials.AnonymousCredentials(), + ) + assert client.api_endpoint == api_override + + # If ClientOptions.api_endpoint is not set and GOOGLE_API_USE_MTLS_ENDPOINT="never", + # use the _DEFAULT_ENDPOINT_TEMPLATE populated with GDU as the api endpoint. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): + client = client_class(credentials=ga_credentials.AnonymousCredentials()) + assert client.api_endpoint == default_endpoint + + # If ClientOptions.api_endpoint is not set and GOOGLE_API_USE_MTLS_ENDPOINT="always", + # use the DEFAULT_MTLS_ENDPOINT as the api endpoint. + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): + client = client_class(credentials=ga_credentials.AnonymousCredentials()) + assert client.api_endpoint == client_class.DEFAULT_MTLS_ENDPOINT + + # If ClientOptions.api_endpoint is not set, GOOGLE_API_USE_MTLS_ENDPOINT="auto" (default), + # GOOGLE_API_USE_CLIENT_CERTIFICATE="false" (default), default cert source doesn't exist, + # and ClientOptions.universe_domain="bar.com", + # use the _DEFAULT_ENDPOINT_TEMPLATE populated with universe domain as the api endpoint. + options = client_options.ClientOptions() + universe_exists = hasattr(options, "universe_domain") + if universe_exists: + options = client_options.ClientOptions(universe_domain=mock_universe) + client = client_class( + client_options=options, credentials=ga_credentials.AnonymousCredentials() + ) + else: + client = client_class( + client_options=options, credentials=ga_credentials.AnonymousCredentials() + ) + assert client.api_endpoint == ( + mock_endpoint if universe_exists else default_endpoint + ) + assert client.universe_domain == ( + mock_universe if universe_exists else default_universe + ) + + # If ClientOptions does not have a universe domain attribute and GOOGLE_API_USE_MTLS_ENDPOINT="never", + # use the _DEFAULT_ENDPOINT_TEMPLATE populated with GDU as the api endpoint. + options = client_options.ClientOptions() + if hasattr(options, "universe_domain"): + delattr(options, "universe_domain") + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): + client = client_class( + client_options=options, credentials=ga_credentials.AnonymousCredentials() + ) + assert client.api_endpoint == default_endpoint + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name", + [ + (ProjectServiceClient, transports.ProjectServiceGrpcTransport, "grpc"), + ( + ProjectServiceAsyncClient, + transports.ProjectServiceGrpcAsyncIOTransport, + "grpc_asyncio", + ), + (ProjectServiceClient, transports.ProjectServiceRestTransport, "rest"), + ], +) +def test_project_service_client_client_options_scopes( + client_class, transport_class, transport_name +): + # Check the case scopes are provided. + options = client_options.ClientOptions( + scopes=["1", "2"], + ) + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options, transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file=None, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), + scopes=["1", "2"], + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name,grpc_helpers", + [ + ( + ProjectServiceClient, + transports.ProjectServiceGrpcTransport, + "grpc", + grpc_helpers, + ), + ( + ProjectServiceAsyncClient, + transports.ProjectServiceGrpcAsyncIOTransport, + "grpc_asyncio", + grpc_helpers_async, + ), + (ProjectServiceClient, transports.ProjectServiceRestTransport, "rest", None), + ], +) +def test_project_service_client_client_options_credentials_file( + client_class, transport_class, transport_name, grpc_helpers +): + # Check the case credentials file is provided. + options = client_options.ClientOptions(credentials_file="credentials.json") + + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options, transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file="credentials.json", + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + +def test_project_service_client_client_options_from_dict(): + with mock.patch( + "google.cloud.retail_v2beta.services.project_service.transports.ProjectServiceGrpcTransport.__init__" + ) as grpc_transport: + grpc_transport.return_value = None + client = ProjectServiceClient( + client_options={"api_endpoint": "squid.clam.whelk"} + ) + grpc_transport.assert_called_once_with( + credentials=None, + credentials_file=None, + host="squid.clam.whelk", + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name,grpc_helpers", + [ + ( + ProjectServiceClient, + transports.ProjectServiceGrpcTransport, + "grpc", + grpc_helpers, + ), + ( + ProjectServiceAsyncClient, + transports.ProjectServiceGrpcAsyncIOTransport, + "grpc_asyncio", + grpc_helpers_async, + ), + ], +) +def test_project_service_client_create_channel_credentials_file( + client_class, transport_class, transport_name, grpc_helpers +): + # Check the case credentials file is provided. + options = client_options.ClientOptions(credentials_file="credentials.json") + + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options, transport=transport_name) + patched.assert_called_once_with( + credentials=None, + credentials_file="credentials.json", + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) + + # test that the credentials from file are saved and used as the credentials. + with mock.patch.object( + google.auth, "load_credentials_from_file", autospec=True + ) as load_creds, mock.patch.object( + google.auth, "default", autospec=True + ) as adc, mock.patch.object( + grpc_helpers, "create_channel" + ) as create_channel: + creds = ga_credentials.AnonymousCredentials() + file_creds = ga_credentials.AnonymousCredentials() + load_creds.return_value = (file_creds, None) + adc.return_value = (creds, None) + client = client_class(client_options=options, transport=transport_name) + create_channel.assert_called_with( + "retail.googleapis.com:443", + credentials=file_creds, + credentials_file=None, + quota_project_id=None, + default_scopes=("https://www.googleapis.com/auth/cloud-platform",), + scopes=None, + default_host="retail.googleapis.com", + ssl_credentials=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + +@pytest.mark.parametrize( + "request_type", + [ + project_service.GetAlertConfigRequest, + dict, + ], +) +def test_get_alert_config(request_type, transport: str = "grpc"): + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_alert_config), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = project.AlertConfig( + name="name_value", + ) + response = client.get_alert_config(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = project_service.GetAlertConfigRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, project.AlertConfig) + assert response.name == "name_value" + + +def test_get_alert_config_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_alert_config), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.get_alert_config() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == project_service.GetAlertConfigRequest() + + +def test_get_alert_config_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = project_service.GetAlertConfigRequest( + name="name_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_alert_config), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.get_alert_config(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == project_service.GetAlertConfigRequest( + name="name_value", + ) + + +def test_get_alert_config_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.get_alert_config in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.get_alert_config + ] = mock_rpc + request = {} + client.get_alert_config(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.get_alert_config(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_get_alert_config_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = ProjectServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_alert_config), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + project.AlertConfig( + name="name_value", + ) + ) + response = await client.get_alert_config() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == project_service.GetAlertConfigRequest() + + +@pytest.mark.asyncio +async def test_get_alert_config_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = ProjectServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.get_alert_config + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.AsyncMock() + mock_rpc.return_value = mock.Mock() + client._client._transport._wrapped_methods[ + client._client._transport.get_alert_config + ] = mock_rpc + + request = {} + await client.get_alert_config(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + await client.get_alert_config(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_get_alert_config_async( + transport: str = "grpc_asyncio", request_type=project_service.GetAlertConfigRequest +): + client = ProjectServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_alert_config), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + project.AlertConfig( + name="name_value", + ) + ) + response = await client.get_alert_config(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = project_service.GetAlertConfigRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, project.AlertConfig) + assert response.name == "name_value" + + +@pytest.mark.asyncio +async def test_get_alert_config_async_from_dict(): + await test_get_alert_config_async(request_type=dict) + + +def test_get_alert_config_field_headers(): + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = project_service.GetAlertConfigRequest() + + request.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_alert_config), "__call__") as call: + call.return_value = project.AlertConfig() + client.get_alert_config(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "name=name_value", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_get_alert_config_field_headers_async(): + client = ProjectServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = project_service.GetAlertConfigRequest() + + request.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_alert_config), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(project.AlertConfig()) + await client.get_alert_config(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "name=name_value", + ) in kw["metadata"] + + +def test_get_alert_config_flattened(): + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_alert_config), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = project.AlertConfig() + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.get_alert_config( + name="name_value", + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val + + +def test_get_alert_config_flattened_error(): + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.get_alert_config( + project_service.GetAlertConfigRequest(), + name="name_value", + ) + + +@pytest.mark.asyncio +async def test_get_alert_config_flattened_async(): + client = ProjectServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_alert_config), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = project.AlertConfig() + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(project.AlertConfig()) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.get_alert_config( + name="name_value", + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + arg = args[0].name + mock_val = "name_value" + assert arg == mock_val + + +@pytest.mark.asyncio +async def test_get_alert_config_flattened_error_async(): + client = ProjectServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + await client.get_alert_config( + project_service.GetAlertConfigRequest(), + name="name_value", + ) + + +@pytest.mark.parametrize( + "request_type", + [ + project_service.UpdateAlertConfigRequest, + dict, + ], +) +def test_update_alert_config(request_type, transport: str = "grpc"): + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_alert_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = project.AlertConfig( + name="name_value", + ) + response = client.update_alert_config(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = project_service.UpdateAlertConfigRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, project.AlertConfig) + assert response.name == "name_value" + + +def test_update_alert_config_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_alert_config), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.update_alert_config() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == project_service.UpdateAlertConfigRequest() + + +def test_update_alert_config_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = project_service.UpdateAlertConfigRequest() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_alert_config), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.update_alert_config(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == project_service.UpdateAlertConfigRequest() + + +def test_update_alert_config_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.update_alert_config in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.update_alert_config + ] = mock_rpc + request = {} + client.update_alert_config(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.update_alert_config(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_update_alert_config_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = ProjectServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_alert_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + project.AlertConfig( + name="name_value", + ) + ) + response = await client.update_alert_config() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == project_service.UpdateAlertConfigRequest() + + +@pytest.mark.asyncio +async def test_update_alert_config_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = ProjectServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.update_alert_config + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.AsyncMock() + mock_rpc.return_value = mock.Mock() + client._client._transport._wrapped_methods[ + client._client._transport.update_alert_config + ] = mock_rpc + + request = {} + await client.update_alert_config(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + await client.update_alert_config(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_update_alert_config_async( + transport: str = "grpc_asyncio", + request_type=project_service.UpdateAlertConfigRequest, +): + client = ProjectServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_alert_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + project.AlertConfig( + name="name_value", + ) + ) + response = await client.update_alert_config(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = project_service.UpdateAlertConfigRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, project.AlertConfig) + assert response.name == "name_value" + + +@pytest.mark.asyncio +async def test_update_alert_config_async_from_dict(): + await test_update_alert_config_async(request_type=dict) + + +def test_update_alert_config_field_headers(): + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = project_service.UpdateAlertConfigRequest() + + request.alert_config.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_alert_config), "__call__" + ) as call: + call.return_value = project.AlertConfig() + client.update_alert_config(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "alert_config.name=name_value", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_update_alert_config_field_headers_async(): + client = ProjectServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = project_service.UpdateAlertConfigRequest() + + request.alert_config.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_alert_config), "__call__" + ) as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(project.AlertConfig()) + await client.update_alert_config(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "alert_config.name=name_value", + ) in kw["metadata"] + + +def test_update_alert_config_flattened(): + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_alert_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = project.AlertConfig() + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.update_alert_config( + alert_config=project.AlertConfig(name="name_value"), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + arg = args[0].alert_config + mock_val = project.AlertConfig(name="name_value") + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val + + +def test_update_alert_config_flattened_error(): + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.update_alert_config( + project_service.UpdateAlertConfigRequest(), + alert_config=project.AlertConfig(name="name_value"), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + +@pytest.mark.asyncio +async def test_update_alert_config_flattened_async(): + client = ProjectServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_alert_config), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = project.AlertConfig() + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(project.AlertConfig()) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.update_alert_config( + alert_config=project.AlertConfig(name="name_value"), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + arg = args[0].alert_config + mock_val = project.AlertConfig(name="name_value") + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val + + +@pytest.mark.asyncio +async def test_update_alert_config_flattened_error_async(): + client = ProjectServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + await client.update_alert_config( + project_service.UpdateAlertConfigRequest(), + alert_config=project.AlertConfig(name="name_value"), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + +@pytest.mark.parametrize( + "request_type", + [ + project_service.GetAlertConfigRequest, + dict, + ], +) +def test_get_alert_config_rest(request_type): + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = {"name": "projects/sample1/alertConfig"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = project.AlertConfig( + name="name_value", + ) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = project.AlertConfig.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + response = client.get_alert_config(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, project.AlertConfig) + assert response.name == "name_value" + + +def test_get_alert_config_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.get_alert_config in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.get_alert_config + ] = mock_rpc + + request = {} + client.get_alert_config(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.get_alert_config(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_get_alert_config_rest_required_fields( + request_type=project_service.GetAlertConfigRequest, +): + transport_class = transports.ProjectServiceRestTransport + + request_init = {} + request_init["name"] = "" + request = request_type(**request_init) + pb_request = request_type.pb(request) + jsonified_request = json.loads( + json_format.MessageToJson(pb_request, use_integers_for_enums=False) + ) + + # verify fields with default values are dropped + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).get_alert_config._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + jsonified_request["name"] = "name_value" + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).get_alert_config._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + assert "name" in jsonified_request + assert jsonified_request["name"] == "name_value" + + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = project.AlertConfig() + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # We need to mock transcode() because providing default values + # for required fields will fail the real version if the http_options + # expect actual values for those fields. + with mock.patch.object(path_template, "transcode") as transcode: + # A uri without fields and an empty body will force all the + # request fields to show up in the query_params. + pb_request = request_type.pb(request) + transcode_result = { + "uri": "v1/sample_method", + "method": "get", + "query_params": pb_request, + } + transcode.return_value = transcode_result + + response_value = Response() + response_value.status_code = 200 + + # Convert return value to protobuf type + return_value = project.AlertConfig.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + response = client.get_alert_config(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_get_alert_config_rest_unset_required_fields(): + transport = transports.ProjectServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.get_alert_config._get_unset_required_fields({}) + assert set(unset_fields) == (set(()) & set(("name",))) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_get_alert_config_rest_interceptors(null_interceptor): + transport = transports.ProjectServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.ProjectServiceRestInterceptor(), + ) + client = ProjectServiceClient(transport=transport) + with mock.patch.object( + type(client.transport._session), "request" + ) as req, mock.patch.object( + path_template, "transcode" + ) as transcode, mock.patch.object( + transports.ProjectServiceRestInterceptor, "post_get_alert_config" + ) as post, mock.patch.object( + transports.ProjectServiceRestInterceptor, "pre_get_alert_config" + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = project_service.GetAlertConfigRequest.pb( + project_service.GetAlertConfigRequest() + ) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = Response() + req.return_value.status_code = 200 + req.return_value.request = PreparedRequest() + req.return_value._content = project.AlertConfig.to_json(project.AlertConfig()) + + request = project_service.GetAlertConfigRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = project.AlertConfig() + + client.get_alert_config( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_get_alert_config_rest_bad_request( + transport: str = "rest", request_type=project_service.GetAlertConfigRequest +): + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = {"name": "projects/sample1/alertConfig"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 400 + response_value.request = Request() + req.return_value = response_value + client.get_alert_config(request) + + +def test_get_alert_config_rest_flattened(): + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = project.AlertConfig() + + # get arguments that satisfy an http rule for this method + sample_request = {"name": "projects/sample1/alertConfig"} + + # get truthy value for each flattened field + mock_args = dict( + name="name_value", + ) + mock_args.update(sample_request) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = project.AlertConfig.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + client.get_alert_config(**mock_args) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(req.mock_calls) == 1 + _, args, _ = req.mock_calls[0] + assert path_template.validate( + "%s/v2beta/{name=projects/*/alertConfig}" % client.transport._host, args[1] + ) + + +def test_get_alert_config_rest_flattened_error(transport: str = "rest"): + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.get_alert_config( + project_service.GetAlertConfigRequest(), + name="name_value", + ) + + +def test_get_alert_config_rest_error(): + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + +@pytest.mark.parametrize( + "request_type", + [ + project_service.UpdateAlertConfigRequest, + dict, + ], +) +def test_update_alert_config_rest(request_type): + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = {"alert_config": {"name": "projects/sample1/alertConfig"}} + request_init["alert_config"] = { + "name": "projects/sample1/alertConfig", + "alert_policies": [ + { + "alert_group": "alert_group_value", + "enroll_status": 1, + "recipients": [{"email_address": "email_address_value"}], + } + ], + } + # The version of a generated dependency at test runtime may differ from the version used during generation. + # Delete any fields which are not present in the current runtime dependency + # See https://github.com/googleapis/gapic-generator-python/issues/1748 + + # Determine if the message type is proto-plus or protobuf + test_field = project_service.UpdateAlertConfigRequest.meta.fields["alert_config"] + + def get_message_fields(field): + # Given a field which is a message (composite type), return a list with + # all the fields of the message. + # If the field is not a composite type, return an empty list. + message_fields = [] + + if hasattr(field, "message") and field.message: + is_field_type_proto_plus_type = not hasattr(field.message, "DESCRIPTOR") + + if is_field_type_proto_plus_type: + message_fields = field.message.meta.fields.values() + # Add `# pragma: NO COVER` because there may not be any `*_pb2` field types + else: # pragma: NO COVER + message_fields = field.message.DESCRIPTOR.fields + return message_fields + + runtime_nested_fields = [ + (field.name, nested_field.name) + for field in get_message_fields(test_field) + for nested_field in get_message_fields(field) + ] + + subfields_not_in_runtime = [] + + # For each item in the sample request, create a list of sub fields which are not present at runtime + # Add `# pragma: NO COVER` because this test code will not run if all subfields are present at runtime + for field, value in request_init["alert_config"].items(): # pragma: NO COVER + result = None + is_repeated = False + # For repeated fields + if isinstance(value, list) and len(value): + is_repeated = True + result = value[0] + # For fields where the type is another message + if isinstance(value, dict): + result = value + + if result and hasattr(result, "keys"): + for subfield in result.keys(): + if (field, subfield) not in runtime_nested_fields: + subfields_not_in_runtime.append( + { + "field": field, + "subfield": subfield, + "is_repeated": is_repeated, + } + ) + + # Remove fields from the sample request which are not present in the runtime version of the dependency + # Add `# pragma: NO COVER` because this test code will not run if all subfields are present at runtime + for subfield_to_delete in subfields_not_in_runtime: # pragma: NO COVER + field = subfield_to_delete.get("field") + field_repeated = subfield_to_delete.get("is_repeated") + subfield = subfield_to_delete.get("subfield") + if subfield: + if field_repeated: + for i in range(0, len(request_init["alert_config"][field])): + del request_init["alert_config"][field][i][subfield] + else: + del request_init["alert_config"][field][subfield] + request = request_type(**request_init) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = project.AlertConfig( + name="name_value", + ) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = project.AlertConfig.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + response = client.update_alert_config(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, project.AlertConfig) + assert response.name == "name_value" + + +def test_update_alert_config_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.update_alert_config in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.update_alert_config + ] = mock_rpc + + request = {} + client.update_alert_config(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.update_alert_config(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_update_alert_config_rest_required_fields( + request_type=project_service.UpdateAlertConfigRequest, +): + transport_class = transports.ProjectServiceRestTransport + + request_init = {} + request = request_type(**request_init) + pb_request = request_type.pb(request) + jsonified_request = json.loads( + json_format.MessageToJson(pb_request, use_integers_for_enums=False) + ) + + # verify fields with default values are dropped + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).update_alert_config._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).update_alert_config._get_unset_required_fields(jsonified_request) + # Check that path parameters and body parameters are not mixing in. + assert not set(unset_fields) - set(("update_mask",)) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = project.AlertConfig() + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # We need to mock transcode() because providing default values + # for required fields will fail the real version if the http_options + # expect actual values for those fields. + with mock.patch.object(path_template, "transcode") as transcode: + # A uri without fields and an empty body will force all the + # request fields to show up in the query_params. + pb_request = request_type.pb(request) + transcode_result = { + "uri": "v1/sample_method", + "method": "patch", + "query_params": pb_request, + } + transcode_result["body"] = pb_request + transcode.return_value = transcode_result + + response_value = Response() + response_value.status_code = 200 + + # Convert return value to protobuf type + return_value = project.AlertConfig.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + response = client.update_alert_config(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_update_alert_config_rest_unset_required_fields(): + transport = transports.ProjectServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.update_alert_config._get_unset_required_fields({}) + assert set(unset_fields) == (set(("updateMask",)) & set(("alertConfig",))) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_update_alert_config_rest_interceptors(null_interceptor): + transport = transports.ProjectServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.ProjectServiceRestInterceptor(), + ) + client = ProjectServiceClient(transport=transport) + with mock.patch.object( + type(client.transport._session), "request" + ) as req, mock.patch.object( + path_template, "transcode" + ) as transcode, mock.patch.object( + transports.ProjectServiceRestInterceptor, "post_update_alert_config" + ) as post, mock.patch.object( + transports.ProjectServiceRestInterceptor, "pre_update_alert_config" + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = project_service.UpdateAlertConfigRequest.pb( + project_service.UpdateAlertConfigRequest() + ) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = Response() + req.return_value.status_code = 200 + req.return_value.request = PreparedRequest() + req.return_value._content = project.AlertConfig.to_json(project.AlertConfig()) + + request = project_service.UpdateAlertConfigRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = project.AlertConfig() + + client.update_alert_config( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_update_alert_config_rest_bad_request( + transport: str = "rest", request_type=project_service.UpdateAlertConfigRequest +): + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = {"alert_config": {"name": "projects/sample1/alertConfig"}} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 400 + response_value.request = Request() + req.return_value = response_value + client.update_alert_config(request) + + +def test_update_alert_config_rest_flattened(): + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = project.AlertConfig() + + # get arguments that satisfy an http rule for this method + sample_request = {"alert_config": {"name": "projects/sample1/alertConfig"}} + + # get truthy value for each flattened field + mock_args = dict( + alert_config=project.AlertConfig(name="name_value"), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + mock_args.update(sample_request) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = project.AlertConfig.pb(return_value) + json_return_value = json_format.MessageToJson(return_value) + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + client.update_alert_config(**mock_args) + + # Establish that the underlying call was made with the expected + # request object values. + assert len(req.mock_calls) == 1 + _, args, _ = req.mock_calls[0] + assert path_template.validate( + "%s/v2beta/{alert_config.name=projects/*/alertConfig}" + % client.transport._host, + args[1], + ) + + +def test_update_alert_config_rest_flattened_error(transport: str = "rest"): + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.update_alert_config( + project_service.UpdateAlertConfigRequest(), + alert_config=project.AlertConfig(name="name_value"), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + +def test_update_alert_config_rest_error(): + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + +def test_credentials_transport_error(): + # It is an error to provide credentials and a transport instance. + transport = transports.ProjectServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + with pytest.raises(ValueError): + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # It is an error to provide a credentials file and a transport instance. + transport = transports.ProjectServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + with pytest.raises(ValueError): + client = ProjectServiceClient( + client_options={"credentials_file": "credentials.json"}, + transport=transport, + ) + + # It is an error to provide an api_key and a transport instance. + transport = transports.ProjectServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + options = client_options.ClientOptions() + options.api_key = "api_key" + with pytest.raises(ValueError): + client = ProjectServiceClient( + client_options=options, + transport=transport, + ) + + # It is an error to provide an api_key and a credential. + options = client_options.ClientOptions() + options.api_key = "api_key" + with pytest.raises(ValueError): + client = ProjectServiceClient( + client_options=options, credentials=ga_credentials.AnonymousCredentials() + ) + + # It is an error to provide scopes and a transport instance. + transport = transports.ProjectServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + with pytest.raises(ValueError): + client = ProjectServiceClient( + client_options={"scopes": ["1", "2"]}, + transport=transport, + ) + + +def test_transport_instance(): + # A client may be instantiated with a custom transport instance. + transport = transports.ProjectServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + client = ProjectServiceClient(transport=transport) + assert client.transport is transport + + +def test_transport_get_channel(): + # A client may be instantiated with a custom transport instance. + transport = transports.ProjectServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + channel = transport.grpc_channel + assert channel + + transport = transports.ProjectServiceGrpcAsyncIOTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + channel = transport.grpc_channel + assert channel + + +@pytest.mark.parametrize( + "transport_class", + [ + transports.ProjectServiceGrpcTransport, + transports.ProjectServiceGrpcAsyncIOTransport, + transports.ProjectServiceRestTransport, + ], +) +def test_transport_adc(transport_class): + # Test default credentials are used if not provided. + with mock.patch.object(google.auth, "default") as adc: + adc.return_value = (ga_credentials.AnonymousCredentials(), None) + transport_class() + adc.assert_called_once() + + +@pytest.mark.parametrize( + "transport_name", + [ + "grpc", + "rest", + ], +) +def test_transport_kind(transport_name): + transport = ProjectServiceClient.get_transport_class(transport_name)( + credentials=ga_credentials.AnonymousCredentials(), + ) + assert transport.kind == transport_name + + +def test_transport_grpc_default(): + # A client should use the gRPC transport by default. + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + assert isinstance( + client.transport, + transports.ProjectServiceGrpcTransport, + ) + + +def test_project_service_base_transport_error(): + # Passing both a credentials object and credentials_file should raise an error + with pytest.raises(core_exceptions.DuplicateCredentialArgs): + transport = transports.ProjectServiceTransport( + credentials=ga_credentials.AnonymousCredentials(), + credentials_file="credentials.json", + ) + + +def test_project_service_base_transport(): + # Instantiate the base transport. + with mock.patch( + "google.cloud.retail_v2beta.services.project_service.transports.ProjectServiceTransport.__init__" + ) as Transport: + Transport.return_value = None + transport = transports.ProjectServiceTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Every method on the transport should just blindly + # raise NotImplementedError. + methods = ( + "get_alert_config", + "update_alert_config", + "get_operation", + "list_operations", + ) + for method in methods: + with pytest.raises(NotImplementedError): + getattr(transport, method)(request=object()) + + with pytest.raises(NotImplementedError): + transport.close() + + # Catch all for all remaining methods and properties + remainder = [ + "kind", + ] + for r in remainder: + with pytest.raises(NotImplementedError): + getattr(transport, r)() + + +def test_project_service_base_transport_with_credentials_file(): + # Instantiate the base transport with a credentials file + with mock.patch.object( + google.auth, "load_credentials_from_file", autospec=True + ) as load_creds, mock.patch( + "google.cloud.retail_v2beta.services.project_service.transports.ProjectServiceTransport._prep_wrapped_messages" + ) as Transport: + Transport.return_value = None + load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) + transport = transports.ProjectServiceTransport( + credentials_file="credentials.json", + quota_project_id="octopus", + ) + load_creds.assert_called_once_with( + "credentials.json", + scopes=None, + default_scopes=("https://www.googleapis.com/auth/cloud-platform",), + quota_project_id="octopus", + ) + + +def test_project_service_base_transport_with_adc(): + # Test the default credentials are used if credentials and credentials_file are None. + with mock.patch.object(google.auth, "default", autospec=True) as adc, mock.patch( + "google.cloud.retail_v2beta.services.project_service.transports.ProjectServiceTransport._prep_wrapped_messages" + ) as Transport: + Transport.return_value = None + adc.return_value = (ga_credentials.AnonymousCredentials(), None) + transport = transports.ProjectServiceTransport() + adc.assert_called_once() + + +def test_project_service_auth_adc(): + # If no credentials are provided, we should use ADC credentials. + with mock.patch.object(google.auth, "default", autospec=True) as adc: + adc.return_value = (ga_credentials.AnonymousCredentials(), None) + ProjectServiceClient() + adc.assert_called_once_with( + scopes=None, + default_scopes=("https://www.googleapis.com/auth/cloud-platform",), + quota_project_id=None, + ) + + +@pytest.mark.parametrize( + "transport_class", + [ + transports.ProjectServiceGrpcTransport, + transports.ProjectServiceGrpcAsyncIOTransport, + ], +) +def test_project_service_transport_auth_adc(transport_class): + # If credentials and host are not provided, the transport class should use + # ADC credentials. + with mock.patch.object(google.auth, "default", autospec=True) as adc: + adc.return_value = (ga_credentials.AnonymousCredentials(), None) + transport_class(quota_project_id="octopus", scopes=["1", "2"]) + adc.assert_called_once_with( + scopes=["1", "2"], + default_scopes=("https://www.googleapis.com/auth/cloud-platform",), + quota_project_id="octopus", + ) + + +@pytest.mark.parametrize( + "transport_class", + [ + transports.ProjectServiceGrpcTransport, + transports.ProjectServiceGrpcAsyncIOTransport, + transports.ProjectServiceRestTransport, + ], +) +def test_project_service_transport_auth_gdch_credentials(transport_class): + host = "https://language.com" + api_audience_tests = [None, "https://language2.com"] + api_audience_expect = [host, "https://language2.com"] + for t, e in zip(api_audience_tests, api_audience_expect): + with mock.patch.object(google.auth, "default", autospec=True) as adc: + gdch_mock = mock.MagicMock() + type(gdch_mock).with_gdch_audience = mock.PropertyMock( + return_value=gdch_mock + ) + adc.return_value = (gdch_mock, None) + transport_class(host=host, api_audience=t) + gdch_mock.with_gdch_audience.assert_called_once_with(e) + + +@pytest.mark.parametrize( + "transport_class,grpc_helpers", + [ + (transports.ProjectServiceGrpcTransport, grpc_helpers), + (transports.ProjectServiceGrpcAsyncIOTransport, grpc_helpers_async), + ], +) +def test_project_service_transport_create_channel(transport_class, grpc_helpers): + # If credentials and host are not provided, the transport class should use + # ADC credentials. + with mock.patch.object( + google.auth, "default", autospec=True + ) as adc, mock.patch.object( + grpc_helpers, "create_channel", autospec=True + ) as create_channel: + creds = ga_credentials.AnonymousCredentials() + adc.return_value = (creds, None) + transport_class(quota_project_id="octopus", scopes=["1", "2"]) + + create_channel.assert_called_with( + "retail.googleapis.com:443", + credentials=creds, + credentials_file=None, + quota_project_id="octopus", + default_scopes=("https://www.googleapis.com/auth/cloud-platform",), + scopes=["1", "2"], + default_host="retail.googleapis.com", + ssl_credentials=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + +@pytest.mark.parametrize( + "transport_class", + [ + transports.ProjectServiceGrpcTransport, + transports.ProjectServiceGrpcAsyncIOTransport, + ], +) +def test_project_service_grpc_transport_client_cert_source_for_mtls(transport_class): + cred = ga_credentials.AnonymousCredentials() + + # Check ssl_channel_credentials is used if provided. + with mock.patch.object(transport_class, "create_channel") as mock_create_channel: + mock_ssl_channel_creds = mock.Mock() + transport_class( + host="squid.clam.whelk", + credentials=cred, + ssl_channel_credentials=mock_ssl_channel_creds, + ) + mock_create_channel.assert_called_once_with( + "squid.clam.whelk:443", + credentials=cred, + credentials_file=None, + scopes=None, + ssl_credentials=mock_ssl_channel_creds, + quota_project_id=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + # Check if ssl_channel_credentials is not provided, then client_cert_source_for_mtls + # is used. + with mock.patch.object(transport_class, "create_channel", return_value=mock.Mock()): + with mock.patch("grpc.ssl_channel_credentials") as mock_ssl_cred: + transport_class( + credentials=cred, + client_cert_source_for_mtls=client_cert_source_callback, + ) + expected_cert, expected_key = client_cert_source_callback() + mock_ssl_cred.assert_called_once_with( + certificate_chain=expected_cert, private_key=expected_key + ) + + +def test_project_service_http_transport_client_cert_source_for_mtls(): + cred = ga_credentials.AnonymousCredentials() + with mock.patch( + "google.auth.transport.requests.AuthorizedSession.configure_mtls_channel" + ) as mock_configure_mtls_channel: + transports.ProjectServiceRestTransport( + credentials=cred, client_cert_source_for_mtls=client_cert_source_callback + ) + mock_configure_mtls_channel.assert_called_once_with(client_cert_source_callback) + + +@pytest.mark.parametrize( + "transport_name", + [ + "grpc", + "grpc_asyncio", + "rest", + ], +) +def test_project_service_host_no_port(transport_name): + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + client_options=client_options.ClientOptions( + api_endpoint="retail.googleapis.com" + ), + transport=transport_name, + ) + assert client.transport._host == ( + "retail.googleapis.com:443" + if transport_name in ["grpc", "grpc_asyncio"] + else "https://retail.googleapis.com" + ) + + +@pytest.mark.parametrize( + "transport_name", + [ + "grpc", + "grpc_asyncio", + "rest", + ], +) +def test_project_service_host_with_port(transport_name): + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + client_options=client_options.ClientOptions( + api_endpoint="retail.googleapis.com:8000" + ), + transport=transport_name, + ) + assert client.transport._host == ( + "retail.googleapis.com:8000" + if transport_name in ["grpc", "grpc_asyncio"] + else "https://retail.googleapis.com:8000" + ) + + +@pytest.mark.parametrize( + "transport_name", + [ + "rest", + ], +) +def test_project_service_client_transport_session_collision(transport_name): + creds1 = ga_credentials.AnonymousCredentials() + creds2 = ga_credentials.AnonymousCredentials() + client1 = ProjectServiceClient( + credentials=creds1, + transport=transport_name, + ) + client2 = ProjectServiceClient( + credentials=creds2, + transport=transport_name, + ) + session1 = client1.transport.get_alert_config._session + session2 = client2.transport.get_alert_config._session + assert session1 != session2 + session1 = client1.transport.update_alert_config._session + session2 = client2.transport.update_alert_config._session + assert session1 != session2 + + +def test_project_service_grpc_transport_channel(): + channel = grpc.secure_channel("http://localhost/", grpc.local_channel_credentials()) + + # Check that channel is used if provided. + transport = transports.ProjectServiceGrpcTransport( + host="squid.clam.whelk", + channel=channel, + ) + assert transport.grpc_channel == channel + assert transport._host == "squid.clam.whelk:443" + assert transport._ssl_channel_credentials == None + + +def test_project_service_grpc_asyncio_transport_channel(): + channel = aio.secure_channel("http://localhost/", grpc.local_channel_credentials()) + + # Check that channel is used if provided. + transport = transports.ProjectServiceGrpcAsyncIOTransport( + host="squid.clam.whelk", + channel=channel, + ) + assert transport.grpc_channel == channel + assert transport._host == "squid.clam.whelk:443" + assert transport._ssl_channel_credentials == None + + +# Remove this test when deprecated arguments (api_mtls_endpoint, client_cert_source) are +# removed from grpc/grpc_asyncio transport constructor. +@pytest.mark.parametrize( + "transport_class", + [ + transports.ProjectServiceGrpcTransport, + transports.ProjectServiceGrpcAsyncIOTransport, + ], +) +def test_project_service_transport_channel_mtls_with_client_cert_source( + transport_class, +): + with mock.patch( + "grpc.ssl_channel_credentials", autospec=True + ) as grpc_ssl_channel_cred: + with mock.patch.object( + transport_class, "create_channel" + ) as grpc_create_channel: + mock_ssl_cred = mock.Mock() + grpc_ssl_channel_cred.return_value = mock_ssl_cred + + mock_grpc_channel = mock.Mock() + grpc_create_channel.return_value = mock_grpc_channel + + cred = ga_credentials.AnonymousCredentials() + with pytest.warns(DeprecationWarning): + with mock.patch.object(google.auth, "default") as adc: + adc.return_value = (cred, None) + transport = transport_class( + host="squid.clam.whelk", + api_mtls_endpoint="mtls.squid.clam.whelk", + client_cert_source=client_cert_source_callback, + ) + adc.assert_called_once() + + grpc_ssl_channel_cred.assert_called_once_with( + certificate_chain=b"cert bytes", private_key=b"key bytes" + ) + grpc_create_channel.assert_called_once_with( + "mtls.squid.clam.whelk:443", + credentials=cred, + credentials_file=None, + scopes=None, + ssl_credentials=mock_ssl_cred, + quota_project_id=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + assert transport.grpc_channel == mock_grpc_channel + assert transport._ssl_channel_credentials == mock_ssl_cred + + +# Remove this test when deprecated arguments (api_mtls_endpoint, client_cert_source) are +# removed from grpc/grpc_asyncio transport constructor. +@pytest.mark.parametrize( + "transport_class", + [ + transports.ProjectServiceGrpcTransport, + transports.ProjectServiceGrpcAsyncIOTransport, + ], +) +def test_project_service_transport_channel_mtls_with_adc(transport_class): + mock_ssl_cred = mock.Mock() + with mock.patch.multiple( + "google.auth.transport.grpc.SslCredentials", + __init__=mock.Mock(return_value=None), + ssl_credentials=mock.PropertyMock(return_value=mock_ssl_cred), + ): + with mock.patch.object( + transport_class, "create_channel" + ) as grpc_create_channel: + mock_grpc_channel = mock.Mock() + grpc_create_channel.return_value = mock_grpc_channel + mock_cred = mock.Mock() + + with pytest.warns(DeprecationWarning): + transport = transport_class( + host="squid.clam.whelk", + credentials=mock_cred, + api_mtls_endpoint="mtls.squid.clam.whelk", + client_cert_source=None, + ) + + grpc_create_channel.assert_called_once_with( + "mtls.squid.clam.whelk:443", + credentials=mock_cred, + credentials_file=None, + scopes=None, + ssl_credentials=mock_ssl_cred, + quota_project_id=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + assert transport.grpc_channel == mock_grpc_channel + + +def test_alert_config_path(): + project = "squid" + expected = "projects/{project}/alertConfig".format( + project=project, + ) + actual = ProjectServiceClient.alert_config_path(project) + assert expected == actual + + +def test_parse_alert_config_path(): + expected = { + "project": "clam", + } + path = ProjectServiceClient.alert_config_path(**expected) + + # Check that the path construction is reversible. + actual = ProjectServiceClient.parse_alert_config_path(path) + assert expected == actual + + +def test_common_billing_account_path(): + billing_account = "whelk" + expected = "billingAccounts/{billing_account}".format( + billing_account=billing_account, + ) + actual = ProjectServiceClient.common_billing_account_path(billing_account) + assert expected == actual + + +def test_parse_common_billing_account_path(): + expected = { + "billing_account": "octopus", + } + path = ProjectServiceClient.common_billing_account_path(**expected) + + # Check that the path construction is reversible. + actual = ProjectServiceClient.parse_common_billing_account_path(path) + assert expected == actual + + +def test_common_folder_path(): + folder = "oyster" + expected = "folders/{folder}".format( + folder=folder, + ) + actual = ProjectServiceClient.common_folder_path(folder) + assert expected == actual + + +def test_parse_common_folder_path(): + expected = { + "folder": "nudibranch", + } + path = ProjectServiceClient.common_folder_path(**expected) + + # Check that the path construction is reversible. + actual = ProjectServiceClient.parse_common_folder_path(path) + assert expected == actual + + +def test_common_organization_path(): + organization = "cuttlefish" + expected = "organizations/{organization}".format( + organization=organization, + ) + actual = ProjectServiceClient.common_organization_path(organization) + assert expected == actual + + +def test_parse_common_organization_path(): + expected = { + "organization": "mussel", + } + path = ProjectServiceClient.common_organization_path(**expected) + + # Check that the path construction is reversible. + actual = ProjectServiceClient.parse_common_organization_path(path) + assert expected == actual + + +def test_common_project_path(): + project = "winkle" + expected = "projects/{project}".format( + project=project, + ) + actual = ProjectServiceClient.common_project_path(project) + assert expected == actual + + +def test_parse_common_project_path(): + expected = { + "project": "nautilus", + } + path = ProjectServiceClient.common_project_path(**expected) + + # Check that the path construction is reversible. + actual = ProjectServiceClient.parse_common_project_path(path) + assert expected == actual + + +def test_common_location_path(): + project = "scallop" + location = "abalone" + expected = "projects/{project}/locations/{location}".format( + project=project, + location=location, + ) + actual = ProjectServiceClient.common_location_path(project, location) + assert expected == actual + + +def test_parse_common_location_path(): + expected = { + "project": "squid", + "location": "clam", + } + path = ProjectServiceClient.common_location_path(**expected) + + # Check that the path construction is reversible. + actual = ProjectServiceClient.parse_common_location_path(path) + assert expected == actual + + +def test_client_with_default_client_info(): + client_info = gapic_v1.client_info.ClientInfo() + + with mock.patch.object( + transports.ProjectServiceTransport, "_prep_wrapped_messages" + ) as prep: + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + client_info=client_info, + ) + prep.assert_called_once_with(client_info) + + with mock.patch.object( + transports.ProjectServiceTransport, "_prep_wrapped_messages" + ) as prep: + transport_class = ProjectServiceClient.get_transport_class() + transport = transport_class( + credentials=ga_credentials.AnonymousCredentials(), + client_info=client_info, + ) + prep.assert_called_once_with(client_info) + + +@pytest.mark.asyncio +async def test_transport_close_async(): + client = ProjectServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + with mock.patch.object( + type(getattr(client.transport, "grpc_channel")), "close" + ) as close: + async with client: + close.assert_not_called() + close.assert_called_once() + + +def test_get_operation_rest_bad_request( + transport: str = "rest", request_type=operations_pb2.GetOperationRequest +): + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + request = request_type() + request = json_format.ParseDict( + { + "name": "projects/sample1/locations/sample2/catalogs/sample3/branches/sample4/operations/sample5" + }, + request, + ) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 400 + response_value.request = Request() + req.return_value = response_value + client.get_operation(request) + + +@pytest.mark.parametrize( + "request_type", + [ + operations_pb2.GetOperationRequest, + dict, + ], +) +def test_get_operation_rest(request_type): + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request_init = { + "name": "projects/sample1/locations/sample2/catalogs/sample3/branches/sample4/operations/sample5" + } + request = request_type(**request_init) + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = operations_pb2.Operation() + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + response = client.get_operation(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, operations_pb2.Operation) + + +def test_list_operations_rest_bad_request( + transport: str = "rest", request_type=operations_pb2.ListOperationsRequest +): + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + request = request_type() + request = json_format.ParseDict( + {"name": "projects/sample1/locations/sample2/catalogs/sample3"}, request + ) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 400 + response_value.request = Request() + req.return_value = response_value + client.list_operations(request) + + +@pytest.mark.parametrize( + "request_type", + [ + operations_pb2.ListOperationsRequest, + dict, + ], +) +def test_list_operations_rest(request_type): + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request_init = {"name": "projects/sample1/locations/sample2/catalogs/sample3"} + request = request_type(**request_init) + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = operations_pb2.ListOperationsResponse() + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + response = client.list_operations(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, operations_pb2.ListOperationsResponse) + + +def test_get_operation(transport: str = "grpc"): + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = operations_pb2.GetOperationRequest() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_operation), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.Operation() + response = client.get_operation(request) + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, operations_pb2.Operation) + + +@pytest.mark.asyncio +async def test_get_operation_async(transport: str = "grpc_asyncio"): + client = ProjectServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = operations_pb2.GetOperationRequest() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_operation), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation() + ) + response = await client.get_operation(request) + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, operations_pb2.Operation) + + +def test_get_operation_field_headers(): + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = operations_pb2.GetOperationRequest() + request.name = "locations" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_operation), "__call__") as call: + call.return_value = operations_pb2.Operation() + + client.get_operation(request) + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "name=locations", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_get_operation_field_headers_async(): + client = ProjectServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = operations_pb2.GetOperationRequest() + request.name = "locations" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_operation), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation() + ) + await client.get_operation(request) + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "name=locations", + ) in kw["metadata"] + + +def test_get_operation_from_dict(): + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_operation), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.Operation() + + response = client.get_operation( + request={ + "name": "locations", + } + ) + call.assert_called() + + +@pytest.mark.asyncio +async def test_get_operation_from_dict_async(): + client = ProjectServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_operation), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation() + ) + response = await client.get_operation( + request={ + "name": "locations", + } + ) + call.assert_called() + + +def test_list_operations(transport: str = "grpc"): + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = operations_pb2.ListOperationsRequest() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_operations), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.ListOperationsResponse() + response = client.list_operations(request) + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, operations_pb2.ListOperationsResponse) + + +@pytest.mark.asyncio +async def test_list_operations_async(transport: str = "grpc_asyncio"): + client = ProjectServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = operations_pb2.ListOperationsRequest() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_operations), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.ListOperationsResponse() + ) + response = await client.list_operations(request) + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, operations_pb2.ListOperationsResponse) + + +def test_list_operations_field_headers(): + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = operations_pb2.ListOperationsRequest() + request.name = "locations" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_operations), "__call__") as call: + call.return_value = operations_pb2.ListOperationsResponse() + + client.list_operations(request) + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "name=locations", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_list_operations_field_headers_async(): + client = ProjectServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = operations_pb2.ListOperationsRequest() + request.name = "locations" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_operations), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.ListOperationsResponse() + ) + await client.list_operations(request) + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "name=locations", + ) in kw["metadata"] + + +def test_list_operations_from_dict(): + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_operations), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.ListOperationsResponse() + + response = client.list_operations( + request={ + "name": "locations", + } + ) + call.assert_called() + + +@pytest.mark.asyncio +async def test_list_operations_from_dict_async(): + client = ProjectServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_operations), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.ListOperationsResponse() + ) + response = await client.list_operations( + request={ + "name": "locations", + } + ) + call.assert_called() + + +def test_transport_close(): + transports = { + "rest": "_session", + "grpc": "_grpc_channel", + } + + for transport, close_name in transports.items(): + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + with mock.patch.object( + type(getattr(client.transport, close_name)), "close" + ) as close: + with client: + close.assert_not_called() + close.assert_called_once() + + +def test_client_ctx(): + transports = [ + "rest", + "grpc", + ] + for transport in transports: + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport=transport + ) + # Test client calls underlying transport. + with mock.patch.object(type(client.transport), "close") as close: + close.assert_not_called() + with client: + pass + close.assert_called() + + +@pytest.mark.parametrize( + "client_class,transport_class", + [ + (ProjectServiceClient, transports.ProjectServiceGrpcTransport), + (ProjectServiceAsyncClient, transports.ProjectServiceGrpcAsyncIOTransport), + ], +) +def test_api_key_credentials(client_class, transport_class): + with mock.patch.object( + google.auth._default, "get_api_key_credentials", create=True + ) as get_api_key_credentials: + mock_cred = mock.Mock() + get_api_key_credentials.return_value = mock_cred + options = client_options.ClientOptions() + options.api_key = "api_key" + with mock.patch.object(transport_class, "__init__") as patched: + patched.return_value = None + client = client_class(client_options=options) + patched.assert_called_once_with( + credentials=mock_cred, + credentials_file=None, + host=client._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=client._DEFAULT_UNIVERSE + ), + scopes=None, + client_cert_source_for_mtls=None, + quota_project_id=None, + client_info=transports.base.DEFAULT_CLIENT_INFO, + always_use_jwt_access=True, + api_audience=None, + ) diff --git a/packages/google-cloud-retail/tests/unit/gapic/retail_v2beta/test_user_event_service.py b/packages/google-cloud-retail/tests/unit/gapic/retail_v2beta/test_user_event_service.py index bda4d65dae28..c1f9c3cf9491 100644 --- a/packages/google-cloud-retail/tests/unit/gapic/retail_v2beta/test_user_event_service.py +++ b/packages/google-cloud-retail/tests/unit/gapic/retail_v2beta/test_user_event_service.py @@ -68,6 +68,7 @@ ) from google.cloud.retail_v2beta.types import ( common, + export_config, import_config, product, promotion, @@ -2449,6 +2450,311 @@ async def test_import_user_events_field_headers_async(): ) in kw["metadata"] +@pytest.mark.parametrize( + "request_type", + [ + export_config.ExportUserEventsRequest, + dict, + ], +) +def test_export_user_events(request_type, transport: str = "grpc"): + client = UserEventServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.export_user_events), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.Operation(name="operations/spam") + response = client.export_user_events(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = export_config.ExportUserEventsRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, future.Future) + + +def test_export_user_events_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = UserEventServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.export_user_events), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.export_user_events() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == export_config.ExportUserEventsRequest() + + +def test_export_user_events_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = UserEventServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Populate all string fields in the request which are not UUID4 + # since we want to check that UUID4 are populated automatically + # if they meet the requirements of AIP 4235. + request = export_config.ExportUserEventsRequest( + parent="parent_value", + filter="filter_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.export_user_events), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.export_user_events(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == export_config.ExportUserEventsRequest( + parent="parent_value", + filter="filter_value", + ) + + +def test_export_user_events_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = UserEventServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.export_user_events in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.export_user_events + ] = mock_rpc + request = {} + client.export_user_events(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + # Operation methods call wrapper_fn to build a cached + # client._transport.operations_client instance on first rpc call. + # Subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + client.export_user_events(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_export_user_events_empty_call_async(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = UserEventServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.export_user_events), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/spam") + ) + response = await client.export_user_events() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == export_config.ExportUserEventsRequest() + + +@pytest.mark.asyncio +async def test_export_user_events_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = UserEventServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.export_user_events + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.AsyncMock() + mock_rpc.return_value = mock.Mock() + client._client._transport._wrapped_methods[ + client._client._transport.export_user_events + ] = mock_rpc + + request = {} + await client.export_user_events(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + # Operation methods call wrapper_fn to build a cached + # client._transport.operations_client instance on first rpc call. + # Subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + await client.export_user_events(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_export_user_events_async( + transport: str = "grpc_asyncio", request_type=export_config.ExportUserEventsRequest +): + client = UserEventServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Everything is optional in proto3 as far as the runtime is concerned, + # and we are mocking out the actual API, so just send an empty request. + request = request_type() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.export_user_events), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/spam") + ) + response = await client.export_user_events(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = export_config.ExportUserEventsRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, future.Future) + + +@pytest.mark.asyncio +async def test_export_user_events_async_from_dict(): + await test_export_user_events_async(request_type=dict) + + +def test_export_user_events_field_headers(): + client = UserEventServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = export_config.ExportUserEventsRequest() + + request.parent = "parent_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.export_user_events), "__call__" + ) as call: + call.return_value = operations_pb2.Operation(name="operations/op") + client.export_user_events(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "parent=parent_value", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_export_user_events_field_headers_async(): + client = UserEventServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Any value that is part of the HTTP/1.1 URI should be sent as + # a field header. Set these to a non-empty value. + request = export_config.ExportUserEventsRequest() + + request.parent = "parent_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.export_user_events), "__call__" + ) as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/op") + ) + await client.export_user_events(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "parent=parent_value", + ) in kw["metadata"] + + @pytest.mark.parametrize( "request_type", [ @@ -4031,6 +4337,263 @@ def test_import_user_events_rest_error(): ) +@pytest.mark.parametrize( + "request_type", + [ + export_config.ExportUserEventsRequest, + dict, + ], +) +def test_export_user_events_rest(request_type): + client = UserEventServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = {"parent": "projects/sample1/locations/sample2/catalogs/sample3"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = operations_pb2.Operation(name="operations/spam") + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + response = client.export_user_events(request) + + # Establish that the response is the type that we expect. + assert response.operation.name == "operations/spam" + + +def test_export_user_events_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = UserEventServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.export_user_events in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.export_user_events + ] = mock_rpc + + request = {} + client.export_user_events(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + # Operation methods build a cached wrapper on first rpc call + # subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + client.export_user_events(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_export_user_events_rest_required_fields( + request_type=export_config.ExportUserEventsRequest, +): + transport_class = transports.UserEventServiceRestTransport + + request_init = {} + request_init["parent"] = "" + request = request_type(**request_init) + pb_request = request_type.pb(request) + jsonified_request = json.loads( + json_format.MessageToJson(pb_request, use_integers_for_enums=False) + ) + + # verify fields with default values are dropped + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).export_user_events._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + jsonified_request["parent"] = "parent_value" + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).export_user_events._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + assert "parent" in jsonified_request + assert jsonified_request["parent"] == "parent_value" + + client = UserEventServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = operations_pb2.Operation(name="operations/spam") + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # We need to mock transcode() because providing default values + # for required fields will fail the real version if the http_options + # expect actual values for those fields. + with mock.patch.object(path_template, "transcode") as transcode: + # A uri without fields and an empty body will force all the + # request fields to show up in the query_params. + pb_request = request_type.pb(request) + transcode_result = { + "uri": "v1/sample_method", + "method": "post", + "query_params": pb_request, + } + transcode_result["body"] = pb_request + transcode.return_value = transcode_result + + response_value = Response() + response_value.status_code = 200 + json_return_value = json_format.MessageToJson(return_value) + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + response = client.export_user_events(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_export_user_events_rest_unset_required_fields(): + transport = transports.UserEventServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.export_user_events._get_unset_required_fields({}) + assert set(unset_fields) == ( + set(()) + & set( + ( + "parent", + "outputConfig", + ) + ) + ) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_export_user_events_rest_interceptors(null_interceptor): + transport = transports.UserEventServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.UserEventServiceRestInterceptor(), + ) + client = UserEventServiceClient(transport=transport) + with mock.patch.object( + type(client.transport._session), "request" + ) as req, mock.patch.object( + path_template, "transcode" + ) as transcode, mock.patch.object( + operation.Operation, "_set_result_from_operation" + ), mock.patch.object( + transports.UserEventServiceRestInterceptor, "post_export_user_events" + ) as post, mock.patch.object( + transports.UserEventServiceRestInterceptor, "pre_export_user_events" + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = export_config.ExportUserEventsRequest.pb( + export_config.ExportUserEventsRequest() + ) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = Response() + req.return_value.status_code = 200 + req.return_value.request = PreparedRequest() + req.return_value._content = json_format.MessageToJson( + operations_pb2.Operation() + ) + + request = export_config.ExportUserEventsRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = operations_pb2.Operation() + + client.export_user_events( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_export_user_events_rest_bad_request( + transport: str = "rest", request_type=export_config.ExportUserEventsRequest +): + client = UserEventServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = {"parent": "projects/sample1/locations/sample2/catalogs/sample3"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a BadRequest error. + with mock.patch.object(Session, "request") as req, pytest.raises( + core_exceptions.BadRequest + ): + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 400 + response_value.request = Request() + req.return_value = response_value + client.export_user_events(request) + + +def test_export_user_events_rest_error(): + client = UserEventServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + @pytest.mark.parametrize( "request_type", [ @@ -4423,6 +4986,7 @@ def test_user_event_service_base_transport(): "collect_user_event", "purge_user_events", "import_user_events", + "export_user_events", "rejoin_user_events", "get_operation", "list_operations", @@ -4718,6 +5282,9 @@ def test_user_event_service_client_transport_session_collision(transport_name): session1 = client1.transport.import_user_events._session session2 = client2.transport.import_user_events._session assert session1 != session2 + session1 = client1.transport.export_user_events._session + session2 = client2.transport.export_user_events._session + assert session1 != session2 session1 = client1.transport.rejoin_user_events._session session2 = client2.transport.rejoin_user_events._session assert session1 != session2 diff --git a/scripts/client-post-processing/doc-formatting.yaml b/scripts/client-post-processing/doc-formatting.yaml index 9f73df1685c2..69357a28a85c 100644 --- a/scripts/client-post-processing/doc-formatting.yaml +++ b/scripts/client-post-processing/doc-formatting.yaml @@ -106,11 +106,12 @@ replacements: count: 1 - paths: [ packages/google-cloud-retail/google/cloud/retail_v2alpha/types/project.py, + packages/google-cloud-retail/google/cloud/retail_v2beta/types/project.py, ] before: | \ resource. Format: projects/\*/alertConfig after: " resource. Format: `projects/*/alertConfig`\n" - count: 1 + count: 2 - paths: [ packages/google-cloud-securitycentermanagement/google/cloud/securitycentermanagement_v1/types/security_center_management.py, ]