diff --git a/packages/google-cloud-discoveryengine/docs/discoveryengine_v1/recommendation_service.rst b/packages/google-cloud-discoveryengine/docs/discoveryengine_v1/recommendation_service.rst new file mode 100644 index 000000000000..c19146d41a41 --- /dev/null +++ b/packages/google-cloud-discoveryengine/docs/discoveryengine_v1/recommendation_service.rst @@ -0,0 +1,6 @@ +RecommendationService +--------------------------------------- + +.. automodule:: google.cloud.discoveryengine_v1.services.recommendation_service + :members: + :inherited-members: diff --git a/packages/google-cloud-discoveryengine/docs/discoveryengine_v1/services_.rst b/packages/google-cloud-discoveryengine/docs/discoveryengine_v1/services_.rst index d931db802583..35f5180cc288 100644 --- a/packages/google-cloud-discoveryengine/docs/discoveryengine_v1/services_.rst +++ b/packages/google-cloud-discoveryengine/docs/discoveryengine_v1/services_.rst @@ -8,6 +8,7 @@ Services for Google Cloud Discoveryengine v1 API data_store_service document_service engine_service + recommendation_service schema_service search_service site_search_engine_service diff --git a/packages/google-cloud-discoveryengine/docs/discoveryengine_v1alpha/grounded_generation_service.rst b/packages/google-cloud-discoveryengine/docs/discoveryengine_v1alpha/grounded_generation_service.rst new file mode 100644 index 000000000000..8b1bbc356bfd --- /dev/null +++ b/packages/google-cloud-discoveryengine/docs/discoveryengine_v1alpha/grounded_generation_service.rst @@ -0,0 +1,6 @@ +GroundedGenerationService +------------------------------------------- + +.. automodule:: google.cloud.discoveryengine_v1alpha.services.grounded_generation_service + :members: + :inherited-members: diff --git a/packages/google-cloud-discoveryengine/docs/discoveryengine_v1alpha/project_service.rst b/packages/google-cloud-discoveryengine/docs/discoveryengine_v1alpha/project_service.rst new file mode 100644 index 000000000000..626a47c329a0 --- /dev/null +++ b/packages/google-cloud-discoveryengine/docs/discoveryengine_v1alpha/project_service.rst @@ -0,0 +1,6 @@ +ProjectService +-------------------------------- + +.. automodule:: google.cloud.discoveryengine_v1alpha.services.project_service + :members: + :inherited-members: diff --git a/packages/google-cloud-discoveryengine/docs/discoveryengine_v1alpha/rank_service.rst b/packages/google-cloud-discoveryengine/docs/discoveryengine_v1alpha/rank_service.rst new file mode 100644 index 000000000000..649695ae0c96 --- /dev/null +++ b/packages/google-cloud-discoveryengine/docs/discoveryengine_v1alpha/rank_service.rst @@ -0,0 +1,6 @@ +RankService +----------------------------- + +.. automodule:: google.cloud.discoveryengine_v1alpha.services.rank_service + :members: + :inherited-members: diff --git a/packages/google-cloud-discoveryengine/docs/discoveryengine_v1alpha/services_.rst b/packages/google-cloud-discoveryengine/docs/discoveryengine_v1alpha/services_.rst index aa2f4b4bb8c9..60d803aa16b3 100644 --- a/packages/google-cloud-discoveryengine/docs/discoveryengine_v1alpha/services_.rst +++ b/packages/google-cloud-discoveryengine/docs/discoveryengine_v1alpha/services_.rst @@ -11,6 +11,9 @@ Services for Google Cloud Discoveryengine v1alpha API document_service engine_service estimate_billing_service + grounded_generation_service + project_service + rank_service recommendation_service schema_service search_service diff --git a/packages/google-cloud-discoveryengine/docs/discoveryengine_v1beta/grounded_generation_service.rst b/packages/google-cloud-discoveryengine/docs/discoveryengine_v1beta/grounded_generation_service.rst new file mode 100644 index 000000000000..53ffd2881846 --- /dev/null +++ b/packages/google-cloud-discoveryengine/docs/discoveryengine_v1beta/grounded_generation_service.rst @@ -0,0 +1,6 @@ +GroundedGenerationService +------------------------------------------- + +.. automodule:: google.cloud.discoveryengine_v1beta.services.grounded_generation_service + :members: + :inherited-members: diff --git a/packages/google-cloud-discoveryengine/docs/discoveryengine_v1beta/rank_service.rst b/packages/google-cloud-discoveryengine/docs/discoveryengine_v1beta/rank_service.rst new file mode 100644 index 000000000000..38b6afe91856 --- /dev/null +++ b/packages/google-cloud-discoveryengine/docs/discoveryengine_v1beta/rank_service.rst @@ -0,0 +1,6 @@ +RankService +----------------------------- + +.. automodule:: google.cloud.discoveryengine_v1beta.services.rank_service + :members: + :inherited-members: diff --git a/packages/google-cloud-discoveryengine/docs/discoveryengine_v1beta/services_.rst b/packages/google-cloud-discoveryengine/docs/discoveryengine_v1beta/services_.rst index 19f92972555a..fc408aab147f 100644 --- a/packages/google-cloud-discoveryengine/docs/discoveryengine_v1beta/services_.rst +++ b/packages/google-cloud-discoveryengine/docs/discoveryengine_v1beta/services_.rst @@ -8,6 +8,8 @@ Services for Google Cloud Discoveryengine v1beta API data_store_service document_service engine_service + grounded_generation_service + rank_service recommendation_service schema_service search_service diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine/__init__.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine/__init__.py index 7d3af8c3a442..c26cfa7ca75f 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine/__init__.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine/__init__.py @@ -48,6 +48,18 @@ from google.cloud.discoveryengine_v1beta.services.engine_service.client import ( EngineServiceClient, ) +from google.cloud.discoveryengine_v1beta.services.grounded_generation_service.async_client import ( + GroundedGenerationServiceAsyncClient, +) +from google.cloud.discoveryengine_v1beta.services.grounded_generation_service.client import ( + GroundedGenerationServiceClient, +) +from google.cloud.discoveryengine_v1beta.services.rank_service.async_client import ( + RankServiceAsyncClient, +) +from google.cloud.discoveryengine_v1beta.services.rank_service.client import ( + RankServiceClient, +) from google.cloud.discoveryengine_v1beta.services.recommendation_service.async_client import ( RecommendationServiceAsyncClient, ) @@ -90,6 +102,7 @@ from google.cloud.discoveryengine_v1beta.services.user_event_service.client import ( UserEventServiceClient, ) +from google.cloud.discoveryengine_v1beta.types.answer import Answer from google.cloud.discoveryengine_v1beta.types.common import ( CustomAttribute, DoubleList, @@ -114,14 +127,23 @@ TextInput, ) from google.cloud.discoveryengine_v1beta.types.conversational_search_service import ( + AnswerQueryRequest, + AnswerQueryResponse, ConverseConversationRequest, ConverseConversationResponse, CreateConversationRequest, + CreateSessionRequest, DeleteConversationRequest, + DeleteSessionRequest, + GetAnswerRequest, GetConversationRequest, + GetSessionRequest, ListConversationsRequest, ListConversationsResponse, + ListSessionsRequest, + ListSessionsResponse, UpdateConversationRequest, + UpdateSessionRequest, ) from google.cloud.discoveryengine_v1beta.types.data_store import DataStore from google.cloud.discoveryengine_v1beta.types.data_store_service import ( @@ -155,10 +177,26 @@ GetEngineRequest, ListEnginesRequest, ListEnginesResponse, + PauseEngineRequest, + ResumeEngineRequest, + TuneEngineMetadata, + TuneEngineRequest, + TuneEngineResponse, UpdateEngineRequest, ) +from google.cloud.discoveryengine_v1beta.types.grounded_generation_service import ( + CheckGroundingRequest, + CheckGroundingResponse, + CheckGroundingSpec, +) +from google.cloud.discoveryengine_v1beta.types.grounding import FactChunk, GroundingFact from google.cloud.discoveryengine_v1beta.types.import_config import ( BigQuerySource, + BigtableOptions, + BigtableSource, + CloudSqlSource, + FhirStoreSource, + FirestoreSource, GcsSource, ImportDocumentsMetadata, ImportDocumentsRequest, @@ -170,6 +208,7 @@ ImportUserEventsMetadata, ImportUserEventsRequest, ImportUserEventsResponse, + SpannerSource, ) from google.cloud.discoveryengine_v1beta.types.purge_config import ( PurgeDocumentsMetadata, @@ -179,6 +218,11 @@ PurgeSuggestionDenyListEntriesRequest, PurgeSuggestionDenyListEntriesResponse, ) +from google.cloud.discoveryengine_v1beta.types.rank_service import ( + RankingRecord, + RankRequest, + RankResponse, +) from google.cloud.discoveryengine_v1beta.types.recommendation_service import ( RecommendRequest, RecommendResponse, @@ -211,6 +255,7 @@ ListServingConfigsResponse, UpdateServingConfigRequest, ) +from google.cloud.discoveryengine_v1beta.types.session import Query, Session from google.cloud.discoveryengine_v1beta.types.site_search_engine import ( SiteSearchEngine, SiteVerificationInfo, @@ -271,6 +316,10 @@ "DocumentServiceAsyncClient", "EngineServiceClient", "EngineServiceAsyncClient", + "GroundedGenerationServiceClient", + "GroundedGenerationServiceAsyncClient", + "RankServiceClient", + "RankServiceAsyncClient", "RecommendationServiceClient", "RecommendationServiceAsyncClient", "SchemaServiceClient", @@ -285,6 +334,7 @@ "SiteSearchEngineServiceAsyncClient", "UserEventServiceClient", "UserEventServiceAsyncClient", + "Answer", "CustomAttribute", "DoubleList", "EmbeddingConfig", @@ -302,14 +352,23 @@ "ConversationMessage", "Reply", "TextInput", + "AnswerQueryRequest", + "AnswerQueryResponse", "ConverseConversationRequest", "ConverseConversationResponse", "CreateConversationRequest", + "CreateSessionRequest", "DeleteConversationRequest", + "DeleteSessionRequest", + "GetAnswerRequest", "GetConversationRequest", + "GetSessionRequest", "ListConversationsRequest", "ListConversationsResponse", + "ListSessionsRequest", + "ListSessionsResponse", "UpdateConversationRequest", + "UpdateSessionRequest", "DataStore", "CreateDataStoreMetadata", "CreateDataStoreRequest", @@ -335,8 +394,23 @@ "GetEngineRequest", "ListEnginesRequest", "ListEnginesResponse", + "PauseEngineRequest", + "ResumeEngineRequest", + "TuneEngineMetadata", + "TuneEngineRequest", + "TuneEngineResponse", "UpdateEngineRequest", + "CheckGroundingRequest", + "CheckGroundingResponse", + "CheckGroundingSpec", + "FactChunk", + "GroundingFact", "BigQuerySource", + "BigtableOptions", + "BigtableSource", + "CloudSqlSource", + "FhirStoreSource", + "FirestoreSource", "GcsSource", "ImportDocumentsMetadata", "ImportDocumentsRequest", @@ -348,12 +422,16 @@ "ImportUserEventsMetadata", "ImportUserEventsRequest", "ImportUserEventsResponse", + "SpannerSource", "PurgeDocumentsMetadata", "PurgeDocumentsRequest", "PurgeDocumentsResponse", "PurgeSuggestionDenyListEntriesMetadata", "PurgeSuggestionDenyListEntriesRequest", "PurgeSuggestionDenyListEntriesResponse", + "RankingRecord", + "RankRequest", + "RankResponse", "RecommendRequest", "RecommendResponse", "Schema", @@ -376,6 +454,8 @@ "ListServingConfigsRequest", "ListServingConfigsResponse", "UpdateServingConfigRequest", + "Query", + "Session", "SiteSearchEngine", "SiteVerificationInfo", "TargetSite", diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/__init__.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/__init__.py index 5cf9243971e0..1d8e773dcbae 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/__init__.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/__init__.py @@ -32,6 +32,10 @@ ) from .services.document_service import DocumentServiceAsyncClient, DocumentServiceClient from .services.engine_service import EngineServiceAsyncClient, EngineServiceClient +from .services.recommendation_service import ( + RecommendationServiceAsyncClient, + RecommendationServiceClient, +) from .services.schema_service import SchemaServiceAsyncClient, SchemaServiceClient from .services.search_service import SearchServiceAsyncClient, SearchServiceClient from .services.site_search_engine_service import ( @@ -103,6 +107,11 @@ ) from .types.import_config import ( BigQuerySource, + BigtableOptions, + BigtableSource, + CloudSqlSource, + FhirStoreSource, + FirestoreSource, GcsSource, ImportDocumentsMetadata, ImportDocumentsRequest, @@ -114,6 +123,7 @@ ImportUserEventsMetadata, ImportUserEventsRequest, ImportUserEventsResponse, + SpannerSource, ) from .types.purge_config import ( PurgeDocumentsMetadata, @@ -123,6 +133,7 @@ PurgeSuggestionDenyListEntriesRequest, PurgeSuggestionDenyListEntriesResponse, ) +from .types.recommendation_service import RecommendRequest, RecommendResponse from .types.schema import Schema from .types.schema_service import ( CreateSchemaMetadata, @@ -184,6 +195,7 @@ "DataStoreServiceAsyncClient", "DocumentServiceAsyncClient", "EngineServiceAsyncClient", + "RecommendationServiceAsyncClient", "SchemaServiceAsyncClient", "SearchServiceAsyncClient", "SiteSearchEngineServiceAsyncClient", @@ -195,6 +207,9 @@ "BatchVerifyTargetSitesRequest", "BatchVerifyTargetSitesResponse", "BigQuerySource", + "BigtableOptions", + "BigtableSource", + "CloudSqlSource", "CollectUserEventRequest", "CompleteQueryRequest", "CompleteQueryResponse", @@ -242,6 +257,8 @@ "EngineServiceClient", "FetchDomainVerificationStatusRequest", "FetchDomainVerificationStatusResponse", + "FhirStoreSource", + "FirestoreSource", "GcsSource", "GetConversationRequest", "GetDataStoreRequest", @@ -283,6 +300,9 @@ "PurgeSuggestionDenyListEntriesMetadata", "PurgeSuggestionDenyListEntriesRequest", "PurgeSuggestionDenyListEntriesResponse", + "RecommendRequest", + "RecommendResponse", + "RecommendationServiceClient", "RecrawlUrisMetadata", "RecrawlUrisRequest", "RecrawlUrisResponse", @@ -299,6 +319,7 @@ "SiteSearchEngineServiceClient", "SiteVerificationInfo", "SolutionType", + "SpannerSource", "SuggestionDenyListEntry", "TargetSite", "TextInput", diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/gapic_metadata.json b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/gapic_metadata.json index 1bf52b2c5e3f..5b1a802b399c 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/gapic_metadata.json +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/gapic_metadata.json @@ -490,6 +490,40 @@ } } }, + "RecommendationService": { + "clients": { + "grpc": { + "libraryClient": "RecommendationServiceClient", + "rpcs": { + "Recommend": { + "methods": [ + "recommend" + ] + } + } + }, + "grpc-async": { + "libraryClient": "RecommendationServiceAsyncClient", + "rpcs": { + "Recommend": { + "methods": [ + "recommend" + ] + } + } + }, + "rest": { + "libraryClient": "RecommendationServiceClient", + "rpcs": { + "Recommend": { + "methods": [ + "recommend" + ] + } + } + } + } + }, "SchemaService": { "clients": { "grpc": { diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/data_store_service/async_client.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/data_store_service/async_client.py index 5a8929bfdb09..22a6c764aa55 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/data_store_service/async_client.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/data_store_service/async_client.py @@ -54,7 +54,7 @@ from google.cloud.discoveryengine_v1.types import common from google.cloud.discoveryengine_v1.types import data_store from google.cloud.discoveryengine_v1.types import data_store as gcd_data_store -from google.cloud.discoveryengine_v1.types import data_store_service +from google.cloud.discoveryengine_v1.types import data_store_service, schema from .client import DataStoreServiceClient from .transports.base import DEFAULT_CLIENT_INFO, DataStoreServiceTransport @@ -80,6 +80,8 @@ class DataStoreServiceAsyncClient: parse_collection_path = staticmethod(DataStoreServiceClient.parse_collection_path) data_store_path = staticmethod(DataStoreServiceClient.data_store_path) parse_data_store_path = staticmethod(DataStoreServiceClient.parse_data_store_path) + schema_path = staticmethod(DataStoreServiceClient.schema_path) + parse_schema_path = staticmethod(DataStoreServiceClient.parse_schema_path) common_billing_account_path = staticmethod( DataStoreServiceClient.common_billing_account_path ) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/data_store_service/client.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/data_store_service/client.py index dcf9524aa13b..6aa5e3d64be3 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/data_store_service/client.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/data_store_service/client.py @@ -59,7 +59,7 @@ from google.cloud.discoveryengine_v1.types import common from google.cloud.discoveryengine_v1.types import data_store from google.cloud.discoveryengine_v1.types import data_store as gcd_data_store -from google.cloud.discoveryengine_v1.types import data_store_service +from google.cloud.discoveryengine_v1.types import data_store_service, schema from .transports.base import DEFAULT_CLIENT_INFO, DataStoreServiceTransport from .transports.grpc import DataStoreServiceGrpcTransport @@ -242,6 +242,30 @@ def parse_data_store_path(path: str) -> Dict[str, str]: ) return m.groupdict() if m else {} + @staticmethod + def schema_path( + project: str, + location: str, + data_store: str, + schema: str, + ) -> str: + """Returns a fully-qualified schema string.""" + return "projects/{project}/locations/{location}/dataStores/{data_store}/schemas/{schema}".format( + project=project, + location=location, + data_store=data_store, + schema=schema, + ) + + @staticmethod + def parse_schema_path(path: str) -> Dict[str, str]: + """Parses a schema path into its component segments.""" + m = re.match( + r"^projects/(?P.+?)/locations/(?P.+?)/dataStores/(?P.+?)/schemas/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + @staticmethod def common_billing_account_path( billing_account: str, diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/document_service/async_client.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/document_service/async_client.py index 30b48e6c20da..73ef5603551a 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/document_service/async_client.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/document_service/async_client.py @@ -46,7 +46,9 @@ from google.api_core import operation_async # 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.protobuf import struct_pb2 # type: ignore +from google.protobuf import timestamp_pb2 # type: ignore from google.cloud.discoveryengine_v1.services.document_service import pagers from google.cloud.discoveryengine_v1.types import ( @@ -81,6 +83,8 @@ class DocumentServiceAsyncClient: parse_branch_path = staticmethod(DocumentServiceClient.parse_branch_path) document_path = staticmethod(DocumentServiceClient.document_path) parse_document_path = staticmethod(DocumentServiceClient.parse_document_path) + fhir_store_path = staticmethod(DocumentServiceClient.fhir_store_path) + parse_fhir_store_path = staticmethod(DocumentServiceClient.parse_fhir_store_path) common_billing_account_path = staticmethod( DocumentServiceClient.common_billing_account_path ) @@ -667,10 +671,12 @@ async def update_document( self, request: Optional[Union[document_service.UpdateDocumentRequest, dict]] = None, *, + document: Optional[gcd_document.Document] = 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]] = (), - ) -> document.Document: + ) -> gcd_document.Document: r"""Updates a [Document][google.cloud.discoveryengine.v1.Document]. .. code-block:: python @@ -703,6 +709,32 @@ async def sample_update_document(): The request object. Request message for [DocumentService.UpdateDocument][google.cloud.discoveryengine.v1.DocumentService.UpdateDocument] method. + document (:class:`google.cloud.discoveryengine_v1.types.Document`): + Required. The document to update/create. + + If the caller does not have permission to update the + [Document][google.cloud.discoveryengine.v1.Document], + regardless of whether or not it exists, a + ``PERMISSION_DENIED`` error is returned. + + If the + [Document][google.cloud.discoveryengine.v1.Document] to + update does not exist and + [allow_missing][google.cloud.discoveryengine.v1.UpdateDocumentRequest.allow_missing] + is not set, a ``NOT_FOUND`` error is returned. + + This corresponds to the ``document`` 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 imported 'document' to update. + If not set, will by default update all + fields. + + 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. @@ -717,8 +749,24 @@ async def sample_update_document(): """ # 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([document, 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." + ) + request = document_service.UpdateDocumentRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if document is not None: + request.document = document + 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 = gapic_v1.method_async.wrap_method( diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/document_service/client.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/document_service/client.py index b8f2d074c218..959bc9a647e5 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/document_service/client.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/document_service/client.py @@ -51,7 +51,9 @@ from google.api_core import operation_async # 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.protobuf import struct_pb2 # type: ignore +from google.protobuf import timestamp_pb2 # type: ignore from google.cloud.discoveryengine_v1.services.document_service import pagers from google.cloud.discoveryengine_v1.types import ( @@ -247,6 +249,30 @@ def parse_document_path(path: str) -> Dict[str, str]: ) return m.groupdict() if m else {} + @staticmethod + def fhir_store_path( + project: str, + location: str, + dataset: str, + fhir_store: str, + ) -> str: + """Returns a fully-qualified fhir_store string.""" + return "projects/{project}/locations/{location}/datasets/{dataset}/fhirStores/{fhir_store}".format( + project=project, + location=location, + dataset=dataset, + fhir_store=fhir_store, + ) + + @staticmethod + def parse_fhir_store_path(path: str) -> Dict[str, str]: + """Parses a fhir_store path into its component segments.""" + m = re.match( + r"^projects/(?P.+?)/locations/(?P.+?)/datasets/(?P.+?)/fhirStores/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + @staticmethod def common_billing_account_path( billing_account: str, @@ -1106,10 +1132,12 @@ def update_document( self, request: Optional[Union[document_service.UpdateDocumentRequest, dict]] = None, *, + document: Optional[gcd_document.Document] = 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]] = (), - ) -> document.Document: + ) -> gcd_document.Document: r"""Updates a [Document][google.cloud.discoveryengine.v1.Document]. .. code-block:: python @@ -1142,6 +1170,32 @@ def sample_update_document(): The request object. Request message for [DocumentService.UpdateDocument][google.cloud.discoveryengine.v1.DocumentService.UpdateDocument] method. + document (google.cloud.discoveryengine_v1.types.Document): + Required. The document to update/create. + + If the caller does not have permission to update the + [Document][google.cloud.discoveryengine.v1.Document], + regardless of whether or not it exists, a + ``PERMISSION_DENIED`` error is returned. + + If the + [Document][google.cloud.discoveryengine.v1.Document] to + update does not exist and + [allow_missing][google.cloud.discoveryengine.v1.UpdateDocumentRequest.allow_missing] + is not set, a ``NOT_FOUND`` error is returned. + + This corresponds to the ``document`` 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 imported 'document' to update. + If not set, will by default update all + fields. + + 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. @@ -1156,12 +1210,27 @@ def sample_update_document(): """ # 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([document, 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." + ) + # Minor optimization to avoid making a copy if the user passes # in a document_service.UpdateDocumentRequest. # There's no risk of modifying the input as we've already verified # there are no flattened fields. if not isinstance(request, document_service.UpdateDocumentRequest): request = document_service.UpdateDocumentRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if document is not None: + request.document = document + 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. diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/document_service/transports/base.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/document_service/transports/base.py index c5037a0a428b..3518ecf9fd15 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/document_service/transports/base.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/document_service/transports/base.py @@ -230,7 +230,7 @@ def update_document( self, ) -> Callable[ [document_service.UpdateDocumentRequest], - Union[document.Document, Awaitable[document.Document]], + Union[gcd_document.Document, Awaitable[gcd_document.Document]], ]: raise NotImplementedError() diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/document_service/transports/grpc.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/document_service/transports/grpc.py index dbf715fbcbbe..b8af075959b4 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/document_service/transports/grpc.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/document_service/transports/grpc.py @@ -338,7 +338,7 @@ def create_document( @property def update_document( self, - ) -> Callable[[document_service.UpdateDocumentRequest], document.Document]: + ) -> Callable[[document_service.UpdateDocumentRequest], gcd_document.Document]: r"""Return a callable for the update document method over gRPC. Updates a [Document][google.cloud.discoveryengine.v1.Document]. @@ -357,7 +357,7 @@ def update_document( self._stubs["update_document"] = self.grpc_channel.unary_unary( "/google.cloud.discoveryengine.v1.DocumentService/UpdateDocument", request_serializer=document_service.UpdateDocumentRequest.serialize, - response_deserializer=document.Document.deserialize, + response_deserializer=gcd_document.Document.deserialize, ) return self._stubs["update_document"] diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/document_service/transports/grpc_asyncio.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/document_service/transports/grpc_asyncio.py index 484cf66f33fd..5de3e29c1b84 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/document_service/transports/grpc_asyncio.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/document_service/transports/grpc_asyncio.py @@ -347,7 +347,7 @@ def create_document( def update_document( self, ) -> Callable[ - [document_service.UpdateDocumentRequest], Awaitable[document.Document] + [document_service.UpdateDocumentRequest], Awaitable[gcd_document.Document] ]: r"""Return a callable for the update document method over gRPC. @@ -367,7 +367,7 @@ def update_document( self._stubs["update_document"] = self.grpc_channel.unary_unary( "/google.cloud.discoveryengine.v1.DocumentService/UpdateDocument", request_serializer=document_service.UpdateDocumentRequest.serialize, - response_deserializer=document.Document.deserialize, + response_deserializer=gcd_document.Document.deserialize, ) return self._stubs["update_document"] diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/document_service/transports/rest.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/document_service/transports/rest.py index ecca9d04d742..534bc0ece61a 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/document_service/transports/rest.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/document_service/transports/rest.py @@ -274,7 +274,9 @@ def pre_update_document( """ return request, metadata - def post_update_document(self, response: document.Document) -> document.Document: + def post_update_document( + self, response: gcd_document.Document + ) -> gcd_document.Document: """Post-rpc interceptor for update_document Override in a subclass to manipulate the response @@ -1173,7 +1175,7 @@ def __call__( retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: Optional[float] = None, metadata: Sequence[Tuple[str, str]] = (), - ) -> document.Document: + ) -> gcd_document.Document: r"""Call the update document method over HTTP. Args: @@ -1188,7 +1190,7 @@ def __call__( sent along with the request as metadata. Returns: - ~.document.Document: + ~.gcd_document.Document: Document captures all raw metadata information of items to be recommended or searched. @@ -1247,8 +1249,8 @@ def __call__( raise core_exceptions.from_http_response(response) # Return the response - resp = document.Document() - pb_resp = document.Document.pb(resp) + resp = gcd_document.Document() + pb_resp = gcd_document.Document.pb(resp) json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) resp = self._interceptor.post_update_document(resp) @@ -1307,7 +1309,7 @@ def purge_documents( @property def update_document( self, - ) -> Callable[[document_service.UpdateDocumentRequest], document.Document]: + ) -> Callable[[document_service.UpdateDocumentRequest], gcd_document.Document]: # 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._UpdateDocument(self._session, self._host, self._interceptor) # type: ignore diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/engine_service/async_client.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/engine_service/async_client.py index 51182da1699f..be4c0593da43 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/engine_service/async_client.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/engine_service/async_client.py @@ -298,7 +298,7 @@ async def sample_create_engine(): # Initialize request argument(s) engine = discoveryengine_v1.Engine() engine.display_name = "display_name_value" - engine.solution_type = "SOLUTION_TYPE_CHAT" + engine.solution_type = "SOLUTION_TYPE_GENERATIVE_CHAT" request = discoveryengine_v1.CreateEngineRequest( parent="parent_value", @@ -590,7 +590,7 @@ async def sample_update_engine(): # Initialize request argument(s) engine = discoveryengine_v1.Engine() engine.display_name = "display_name_value" - engine.solution_type = "SOLUTION_TYPE_CHAT" + engine.solution_type = "SOLUTION_TYPE_GENERATIVE_CHAT" request = discoveryengine_v1.UpdateEngineRequest( engine=engine, diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/engine_service/client.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/engine_service/client.py index b0dad2dc46f8..c14f1aeb32d9 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/engine_service/client.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/engine_service/client.py @@ -733,7 +733,7 @@ def sample_create_engine(): # Initialize request argument(s) engine = discoveryengine_v1.Engine() engine.display_name = "display_name_value" - engine.solution_type = "SOLUTION_TYPE_CHAT" + engine.solution_type = "SOLUTION_TYPE_GENERATIVE_CHAT" request = discoveryengine_v1.CreateEngineRequest( parent="parent_value", @@ -1025,7 +1025,7 @@ def sample_update_engine(): # Initialize request argument(s) engine = discoveryengine_v1.Engine() engine.display_name = "display_name_value" - engine.solution_type = "SOLUTION_TYPE_CHAT" + engine.solution_type = "SOLUTION_TYPE_GENERATIVE_CHAT" request = discoveryengine_v1.UpdateEngineRequest( engine=engine, diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/recommendation_service/__init__.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/recommendation_service/__init__.py new file mode 100644 index 000000000000..7ac72f000940 --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/recommendation_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 RecommendationServiceAsyncClient +from .client import RecommendationServiceClient + +__all__ = ( + "RecommendationServiceClient", + "RecommendationServiceAsyncClient", +) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/recommendation_service/async_client.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/recommendation_service/async_client.py new file mode 100644 index 000000000000..766cc518c321 --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/recommendation_service/async_client.py @@ -0,0 +1,480 @@ +# -*- 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 functools +import re +from typing import ( + 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.discoveryengine_v1 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.cloud.discoveryengine_v1.types import recommendation_service + +from .client import RecommendationServiceClient +from .transports.base import DEFAULT_CLIENT_INFO, RecommendationServiceTransport +from .transports.grpc_asyncio import RecommendationServiceGrpcAsyncIOTransport + + +class RecommendationServiceAsyncClient: + """Service for making recommendations.""" + + _client: RecommendationServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = RecommendationServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = RecommendationServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = RecommendationServiceClient._DEFAULT_ENDPOINT_TEMPLATE + _DEFAULT_UNIVERSE = RecommendationServiceClient._DEFAULT_UNIVERSE + + document_path = staticmethod(RecommendationServiceClient.document_path) + parse_document_path = staticmethod(RecommendationServiceClient.parse_document_path) + serving_config_path = staticmethod(RecommendationServiceClient.serving_config_path) + parse_serving_config_path = staticmethod( + RecommendationServiceClient.parse_serving_config_path + ) + common_billing_account_path = staticmethod( + RecommendationServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + RecommendationServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod(RecommendationServiceClient.common_folder_path) + parse_common_folder_path = staticmethod( + RecommendationServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + RecommendationServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + RecommendationServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod(RecommendationServiceClient.common_project_path) + parse_common_project_path = staticmethod( + RecommendationServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + RecommendationServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + RecommendationServiceClient.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: + RecommendationServiceAsyncClient: The constructed client. + """ + return RecommendationServiceClient.from_service_account_info.__func__(RecommendationServiceAsyncClient, 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: + RecommendationServiceAsyncClient: The constructed client. + """ + return RecommendationServiceClient.from_service_account_file.__func__(RecommendationServiceAsyncClient, 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 RecommendationServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> RecommendationServiceTransport: + """Returns the transport used by the client instance. + + Returns: + RecommendationServiceTransport: 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 = functools.partial( + type(RecommendationServiceClient).get_transport_class, + type(RecommendationServiceClient), + ) + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Union[str, RecommendationServiceTransport] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the recommendation 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 (Union[str, ~.RecommendationServiceTransport]): The + transport to use. 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 = RecommendationServiceClient( + credentials=credentials, + transport=transport, + client_options=client_options, + client_info=client_info, + ) + + async def recommend( + self, + request: Optional[Union[recommendation_service.RecommendRequest, dict]] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> recommendation_service.RecommendResponse: + r"""Makes a recommendation, which requires a contextual + user event. + + .. 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 discoveryengine_v1 + + async def sample_recommend(): + # Create a client + client = discoveryengine_v1.RecommendationServiceAsyncClient() + + # Initialize request argument(s) + user_event = discoveryengine_v1.UserEvent() + user_event.event_type = "event_type_value" + user_event.user_pseudo_id = "user_pseudo_id_value" + + request = discoveryengine_v1.RecommendRequest( + serving_config="serving_config_value", + user_event=user_event, + ) + + # Make the request + response = await client.recommend(request=request) + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.discoveryengine_v1.types.RecommendRequest, dict]]): + The request object. Request message for Recommend 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.cloud.discoveryengine_v1.types.RecommendResponse: + Response message for Recommend + method. + + """ + # Create or coerce a protobuf request object. + request = recommendation_service.RecommendRequest(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.recommend, + 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( + (("serving_config", request.serving_config),) + ), + ) + + # 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) -> "RecommendationServiceAsyncClient": + 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__ = ("RecommendationServiceAsyncClient",) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/recommendation_service/client.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/recommendation_service/client.py new file mode 100644 index 000000000000..97cb26251fe4 --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/recommendation_service/client.py @@ -0,0 +1,924 @@ +# -*- 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 ( + 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.discoveryengine_v1 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.cloud.discoveryengine_v1.types import recommendation_service + +from .transports.base import DEFAULT_CLIENT_INFO, RecommendationServiceTransport +from .transports.grpc import RecommendationServiceGrpcTransport +from .transports.grpc_asyncio import RecommendationServiceGrpcAsyncIOTransport +from .transports.rest import RecommendationServiceRestTransport + + +class RecommendationServiceClientMeta(type): + """Metaclass for the RecommendationService 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[RecommendationServiceTransport]] + _transport_registry["grpc"] = RecommendationServiceGrpcTransport + _transport_registry["grpc_asyncio"] = RecommendationServiceGrpcAsyncIOTransport + _transport_registry["rest"] = RecommendationServiceRestTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[RecommendationServiceTransport]: + """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 RecommendationServiceClient(metaclass=RecommendationServiceClientMeta): + """Service for making recommendations.""" + + @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 = "discoveryengine.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "discoveryengine.{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: + RecommendationServiceClient: 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: + RecommendationServiceClient: 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) -> RecommendationServiceTransport: + """Returns the transport used by the client instance. + + Returns: + RecommendationServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def document_path( + project: str, + location: str, + data_store: str, + branch: str, + document: str, + ) -> str: + """Returns a fully-qualified document string.""" + return "projects/{project}/locations/{location}/dataStores/{data_store}/branches/{branch}/documents/{document}".format( + project=project, + location=location, + data_store=data_store, + branch=branch, + document=document, + ) + + @staticmethod + def parse_document_path(path: str) -> Dict[str, str]: + """Parses a document path into its component segments.""" + m = re.match( + r"^projects/(?P.+?)/locations/(?P.+?)/dataStores/(?P.+?)/branches/(?P.+?)/documents/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def serving_config_path( + project: str, + location: str, + data_store: str, + serving_config: str, + ) -> str: + """Returns a fully-qualified serving_config string.""" + return "projects/{project}/locations/{location}/dataStores/{data_store}/servingConfigs/{serving_config}".format( + project=project, + location=location, + data_store=data_store, + serving_config=serving_config, + ) + + @staticmethod + def parse_serving_config_path(path: str) -> Dict[str, str]: + """Parses a serving_config path into its component segments.""" + m = re.match( + r"^projects/(?P.+?)/locations/(?P.+?)/dataStores/(?P.+?)/servingConfigs/(?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 = RecommendationServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = RecommendationServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + RecommendationServiceClient._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 = RecommendationServiceClient._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 = RecommendationServiceClient._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 RecommendationServiceClient._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, RecommendationServiceTransport]] = None, + client_options: Optional[Union[client_options_lib.ClientOptions, dict]] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the recommendation 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 (Union[str, RecommendationServiceTransport]): The + transport to use. 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, + ) = RecommendationServiceClient._read_environment_variables() + self._client_cert_source = RecommendationServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + self._universe_domain = RecommendationServiceClient._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, RecommendationServiceTransport) + if transport_provided: + # transport is a RecommendationServiceTransport 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(RecommendationServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or RecommendationServiceClient._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 = type(self).get_transport_class(cast(str, transport)) + self._transport = Transport( + 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 recommend( + self, + request: Optional[Union[recommendation_service.RecommendRequest, dict]] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> recommendation_service.RecommendResponse: + r"""Makes a recommendation, which requires a contextual + user event. + + .. 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 discoveryengine_v1 + + def sample_recommend(): + # Create a client + client = discoveryengine_v1.RecommendationServiceClient() + + # Initialize request argument(s) + user_event = discoveryengine_v1.UserEvent() + user_event.event_type = "event_type_value" + user_event.user_pseudo_id = "user_pseudo_id_value" + + request = discoveryengine_v1.RecommendRequest( + serving_config="serving_config_value", + user_event=user_event, + ) + + # Make the request + response = client.recommend(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.discoveryengine_v1.types.RecommendRequest, dict]): + The request object. Request message for Recommend 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.cloud.discoveryengine_v1.types.RecommendResponse: + Response message for Recommend + method. + + """ + # Create or coerce a protobuf request object. + # Minor optimization to avoid making a copy if the user passes + # in a recommendation_service.RecommendRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance(request, recommendation_service.RecommendRequest): + request = recommendation_service.RecommendRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.recommend] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("serving_config", request.serving_config),) + ), + ) + + # 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) -> "RecommendationServiceClient": + 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__ = ("RecommendationServiceClient",) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/recommendation_service/transports/__init__.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/recommendation_service/transports/__init__.py new file mode 100644 index 000000000000..0caa2a7c212e --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/recommendation_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 RecommendationServiceTransport +from .grpc import RecommendationServiceGrpcTransport +from .grpc_asyncio import RecommendationServiceGrpcAsyncIOTransport +from .rest import ( + RecommendationServiceRestInterceptor, + RecommendationServiceRestTransport, +) + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[RecommendationServiceTransport]] +_transport_registry["grpc"] = RecommendationServiceGrpcTransport +_transport_registry["grpc_asyncio"] = RecommendationServiceGrpcAsyncIOTransport +_transport_registry["rest"] = RecommendationServiceRestTransport + +__all__ = ( + "RecommendationServiceTransport", + "RecommendationServiceGrpcTransport", + "RecommendationServiceGrpcAsyncIOTransport", + "RecommendationServiceRestTransport", + "RecommendationServiceRestInterceptor", +) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/recommendation_service/transports/base.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/recommendation_service/transports/base.py new file mode 100644 index 000000000000..c138b8e24ed0 --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/recommendation_service/transports/base.py @@ -0,0 +1,185 @@ +# -*- 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.discoveryengine_v1 import gapic_version as package_version +from google.cloud.discoveryengine_v1.types import recommendation_service + +DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=package_version.__version__ +) + + +class RecommendationServiceTransport(abc.ABC): + """Abstract transport class for RecommendationService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/cloud-platform",) + + DEFAULT_HOST: str = "discoveryengine.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: 'discoveryengine.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 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: + 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.recommend: gapic_v1.method.wrap_method( + self.recommend, + 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 recommend( + self, + ) -> Callable[ + [recommendation_service.RecommendRequest], + Union[ + recommendation_service.RecommendResponse, + Awaitable[recommendation_service.RecommendResponse], + ], + ]: + 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__ = ("RecommendationServiceTransport",) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/recommendation_service/transports/grpc.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/recommendation_service/transports/grpc.py new file mode 100644 index 000000000000..14a584b159bb --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/recommendation_service/transports/grpc.py @@ -0,0 +1,307 @@ +# -*- 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.discoveryengine_v1.types import recommendation_service + +from .base import DEFAULT_CLIENT_INFO, RecommendationServiceTransport + + +class RecommendationServiceGrpcTransport(RecommendationServiceTransport): + """gRPC backend transport for RecommendationService. + + Service for making recommendations. + + 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 = "discoveryengine.googleapis.com", + credentials: Optional[ga_credentials.Credentials] = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + channel: Optional[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: 'discoveryengine.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 ``channel`` 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 ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): 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 ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + 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 channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + 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: + self._grpc_channel = type(self).create_channel( + 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 = "discoveryengine.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 recommend( + self, + ) -> Callable[ + [recommendation_service.RecommendRequest], + recommendation_service.RecommendResponse, + ]: + r"""Return a callable for the recommend method over gRPC. + + Makes a recommendation, which requires a contextual + user event. + + Returns: + Callable[[~.RecommendRequest], + ~.RecommendResponse]: + 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 "recommend" not in self._stubs: + self._stubs["recommend"] = self.grpc_channel.unary_unary( + "/google.cloud.discoveryengine.v1.RecommendationService/Recommend", + request_serializer=recommendation_service.RecommendRequest.serialize, + response_deserializer=recommendation_service.RecommendResponse.deserialize, + ) + return self._stubs["recommend"] + + 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__ = ("RecommendationServiceGrpcTransport",) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/recommendation_service/transports/grpc_asyncio.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/recommendation_service/transports/grpc_asyncio.py new file mode 100644 index 000000000000..d1a66818167d --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/recommendation_service/transports/grpc_asyncio.py @@ -0,0 +1,306 @@ +# -*- 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 gapic_v1, grpc_helpers_async +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.discoveryengine_v1.types import recommendation_service + +from .base import DEFAULT_CLIENT_INFO, RecommendationServiceTransport +from .grpc import RecommendationServiceGrpcTransport + + +class RecommendationServiceGrpcAsyncIOTransport(RecommendationServiceTransport): + """gRPC AsyncIO backend transport for RecommendationService. + + Service for making recommendations. + + 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 = "discoveryengine.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`. + This argument is ignored if ``channel`` 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`. + 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 = "discoveryengine.googleapis.com", + credentials: Optional[ga_credentials.Credentials] = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + channel: Optional[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: 'discoveryengine.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 ``channel`` 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 ``channel`` 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[aio.Channel]): A ``Channel`` instance through + which to make calls. + 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 ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + 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 channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + 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: + self._grpc_channel = type(self).create_channel( + 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 recommend( + self, + ) -> Callable[ + [recommendation_service.RecommendRequest], + Awaitable[recommendation_service.RecommendResponse], + ]: + r"""Return a callable for the recommend method over gRPC. + + Makes a recommendation, which requires a contextual + user event. + + Returns: + Callable[[~.RecommendRequest], + Awaitable[~.RecommendResponse]]: + 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 "recommend" not in self._stubs: + self._stubs["recommend"] = self.grpc_channel.unary_unary( + "/google.cloud.discoveryengine.v1.RecommendationService/Recommend", + request_serializer=recommendation_service.RecommendRequest.serialize, + response_deserializer=recommendation_service.RecommendResponse.deserialize, + ) + return self._stubs["recommend"] + + 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__ = ("RecommendationServiceGrpcAsyncIOTransport",) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/recommendation_service/transports/rest.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/recommendation_service/transports/rest.py new file mode 100644 index 000000000000..ada02cbdf27a --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/recommendation_service/transports/rest.py @@ -0,0 +1,616 @@ +# -*- 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.discoveryengine_v1.types import recommendation_service + +from .base import DEFAULT_CLIENT_INFO as BASE_DEFAULT_CLIENT_INFO +from .base import RecommendationServiceTransport + +DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=BASE_DEFAULT_CLIENT_INFO.gapic_version, + grpc_version=None, + rest_version=requests_version, +) + + +class RecommendationServiceRestInterceptor: + """Interceptor for RecommendationService. + + 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 RecommendationServiceRestTransport. + + .. code-block:: python + class MyCustomRecommendationServiceInterceptor(RecommendationServiceRestInterceptor): + def pre_recommend(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_recommend(self, response): + logging.log(f"Received response: {response}") + return response + + transport = RecommendationServiceRestTransport(interceptor=MyCustomRecommendationServiceInterceptor()) + client = RecommendationServiceClient(transport=transport) + + + """ + + def pre_recommend( + self, + request: recommendation_service.RecommendRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[recommendation_service.RecommendRequest, Sequence[Tuple[str, str]]]: + """Pre-rpc interceptor for recommend + + Override in a subclass to manipulate the request or metadata + before they are sent to the RecommendationService server. + """ + return request, metadata + + def post_recommend( + self, response: recommendation_service.RecommendResponse + ) -> recommendation_service.RecommendResponse: + """Post-rpc interceptor for recommend + + Override in a subclass to manipulate the response + after it is returned by the RecommendationService 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 RecommendationService 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 RecommendationService 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 RecommendationService 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 RecommendationService server but before + it is returned to user code. + """ + return response + + +@dataclasses.dataclass +class RecommendationServiceRestStub: + _session: AuthorizedSession + _host: str + _interceptor: RecommendationServiceRestInterceptor + + +class RecommendationServiceRestTransport(RecommendationServiceTransport): + """REST backend transport for RecommendationService. + + Service for making recommendations. + + 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 = "discoveryengine.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[RecommendationServiceRestInterceptor] = None, + api_audience: Optional[str] = None, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to (default: 'discoveryengine.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 RecommendationServiceRestInterceptor() + self._prep_wrapped_messages(client_info) + + class _Recommend(RecommendationServiceRestStub): + def __hash__(self): + return hash("Recommend") + + __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: recommendation_service.RecommendRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> recommendation_service.RecommendResponse: + r"""Call the recommend method over HTTP. + + Args: + request (~.recommendation_service.RecommendRequest): + The request object. Request message for Recommend 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: + ~.recommendation_service.RecommendResponse: + Response message for Recommend + method. + + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "post", + "uri": "/v1/{serving_config=projects/*/locations/*/dataStores/*/servingConfigs/*}:recommend", + "body": "*", + }, + { + "method": "post", + "uri": "/v1/{serving_config=projects/*/locations/*/collections/*/dataStores/*/servingConfigs/*}:recommend", + "body": "*", + }, + { + "method": "post", + "uri": "/v1/{serving_config=projects/*/locations/*/collections/*/engines/*/servingConfigs/*}:recommend", + "body": "*", + }, + ] + request, metadata = self._interceptor.pre_recommend(request, metadata) + pb_request = recommendation_service.RecommendRequest.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 = recommendation_service.RecommendResponse() + pb_resp = recommendation_service.RecommendResponse.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + resp = self._interceptor.post_recommend(resp) + return resp + + @property + def recommend( + self, + ) -> Callable[ + [recommendation_service.RecommendRequest], + recommendation_service.RecommendResponse, + ]: + # 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._Recommend(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(RecommendationServiceRestStub): + 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": "/v1/{name=projects/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1/{name=projects/*/locations/*/collections/*/dataConnector/operations/*}", + }, + { + "method": "get", + "uri": "/v1/{name=projects/*/locations/*/collections/*/dataStores/*/branches/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1/{name=projects/*/locations/*/collections/*/dataStores/*/models/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1/{name=projects/*/locations/*/collections/*/dataStores/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1/{name=projects/*/locations/*/collections/*/dataStores/*/schemas/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1/{name=projects/*/locations/*/collections/*/dataStores/*/siteSearchEngine/operations/*}", + }, + { + "method": "get", + "uri": "/v1/{name=projects/*/locations/*/collections/*/dataStores/*/siteSearchEngine/targetSites/operations/*}", + }, + { + "method": "get", + "uri": "/v1/{name=projects/*/locations/*/collections/*/engines/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1/{name=projects/*/locations/*/collections/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1/{name=projects/*/locations/*/dataStores/*/branches/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1/{name=projects/*/locations/*/dataStores/*/models/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1/{name=projects/*/locations/*/dataStores/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1/{name=projects/*/locations/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1/{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(RecommendationServiceRestStub): + 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": "/v1/{name=projects/*}/operations", + }, + { + "method": "get", + "uri": "/v1/{name=projects/*/locations/*/collections/*/dataConnector}/operations", + }, + { + "method": "get", + "uri": "/v1/{name=projects/*/locations/*/collections/*/dataStores/*/branches/*}/operations", + }, + { + "method": "get", + "uri": "/v1/{name=projects/*/locations/*/collections/*/dataStores/*/models/*}/operations", + }, + { + "method": "get", + "uri": "/v1/{name=projects/*/locations/*/collections/*/dataStores/*/schemas/*}/operations", + }, + { + "method": "get", + "uri": "/v1/{name=projects/*/locations/*/collections/*/dataStores/*/siteSearchEngine/targetSites}/operations", + }, + { + "method": "get", + "uri": "/v1/{name=projects/*/locations/*/collections/*/dataStores/*/siteSearchEngine}/operations", + }, + { + "method": "get", + "uri": "/v1/{name=projects/*/locations/*/collections/*/dataStores/*}/operations", + }, + { + "method": "get", + "uri": "/v1/{name=projects/*/locations/*/collections/*/engines/*}/operations", + }, + { + "method": "get", + "uri": "/v1/{name=projects/*/locations/*/collections/*}/operations", + }, + { + "method": "get", + "uri": "/v1/{name=projects/*/locations/*/dataStores/*/branches/*}/operations", + }, + { + "method": "get", + "uri": "/v1/{name=projects/*/locations/*/dataStores/*/models/*}/operations", + }, + { + "method": "get", + "uri": "/v1/{name=projects/*/locations/*/dataStores/*}/operations", + }, + { + "method": "get", + "uri": "/v1/{name=projects/*/locations/*}/operations", + }, + { + "method": "get", + "uri": "/v1/{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__ = ("RecommendationServiceRestTransport",) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/search_service/async_client.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/search_service/async_client.py index 40ed70a54403..6038a8ef7959 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/search_service/async_client.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/search_service/async_client.py @@ -67,6 +67,8 @@ class SearchServiceAsyncClient: branch_path = staticmethod(SearchServiceClient.branch_path) parse_branch_path = staticmethod(SearchServiceClient.parse_branch_path) + data_store_path = staticmethod(SearchServiceClient.data_store_path) + parse_data_store_path = staticmethod(SearchServiceClient.parse_data_store_path) document_path = staticmethod(SearchServiceClient.document_path) parse_document_path = staticmethod(SearchServiceClient.parse_document_path) serving_config_path = staticmethod(SearchServiceClient.serving_config_path) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/search_service/client.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/search_service/client.py index d557c8b178ff..83928a70d58b 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/search_service/client.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/services/search_service/client.py @@ -207,6 +207,28 @@ def parse_branch_path(path: str) -> Dict[str, str]: ) return m.groupdict() if m else {} + @staticmethod + def data_store_path( + project: str, + location: str, + data_store: str, + ) -> str: + """Returns a fully-qualified data_store string.""" + return "projects/{project}/locations/{location}/dataStores/{data_store}".format( + project=project, + location=location, + data_store=data_store, + ) + + @staticmethod + def parse_data_store_path(path: str) -> Dict[str, str]: + """Parses a data_store path into its component segments.""" + m = re.match( + r"^projects/(?P.+?)/locations/(?P.+?)/dataStores/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + @staticmethod def document_path( project: str, diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/types/__init__.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/types/__init__.py index e483492a66c1..a4eae0066145 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/types/__init__.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/types/__init__.py @@ -74,6 +74,11 @@ ) from .import_config import ( BigQuerySource, + BigtableOptions, + BigtableSource, + CloudSqlSource, + FhirStoreSource, + FirestoreSource, GcsSource, ImportDocumentsMetadata, ImportDocumentsRequest, @@ -85,6 +90,7 @@ ImportUserEventsMetadata, ImportUserEventsRequest, ImportUserEventsResponse, + SpannerSource, ) from .purge_config import ( PurgeDocumentsMetadata, @@ -94,6 +100,7 @@ PurgeSuggestionDenyListEntriesRequest, PurgeSuggestionDenyListEntriesResponse, ) +from .recommendation_service import RecommendRequest, RecommendResponse from .schema import Schema from .schema_service import ( CreateSchemaMetadata, @@ -199,6 +206,11 @@ "ListEnginesResponse", "UpdateEngineRequest", "BigQuerySource", + "BigtableOptions", + "BigtableSource", + "CloudSqlSource", + "FhirStoreSource", + "FirestoreSource", "GcsSource", "ImportDocumentsMetadata", "ImportDocumentsRequest", @@ -210,12 +222,15 @@ "ImportUserEventsMetadata", "ImportUserEventsRequest", "ImportUserEventsResponse", + "SpannerSource", "PurgeDocumentsMetadata", "PurgeDocumentsRequest", "PurgeDocumentsResponse", "PurgeSuggestionDenyListEntriesMetadata", "PurgeSuggestionDenyListEntriesRequest", "PurgeSuggestionDenyListEntriesResponse", + "RecommendRequest", + "RecommendResponse", "Schema", "CreateSchemaMetadata", "CreateSchemaRequest", diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/types/common.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/types/common.py index 69a9642d2362..0dc2c5d3c229 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/types/common.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/types/common.py @@ -45,10 +45,13 @@ class IndustryVertical(proto.Enum): not specific to any industry vertical. MEDIA (2): The media industry vertical. + HEALTHCARE_FHIR (7): + The healthcare FHIR vertical. """ INDUSTRY_VERTICAL_UNSPECIFIED = 0 GENERIC = 1 MEDIA = 2 + HEALTHCARE_FHIR = 7 class SolutionType(proto.Enum): @@ -64,16 +67,22 @@ class SolutionType(proto.Enum): SOLUTION_TYPE_CHAT (3): Used for use cases related to the Generative AI agent. + SOLUTION_TYPE_GENERATIVE_CHAT (4): + Used for use cases related to the Generative Chat agent. + It's used for Generative chat engine only, the associated + data stores must enrolled with ``SOLUTION_TYPE_CHAT`` + solution. """ SOLUTION_TYPE_UNSPECIFIED = 0 SOLUTION_TYPE_RECOMMENDATION = 1 SOLUTION_TYPE_SEARCH = 2 SOLUTION_TYPE_CHAT = 3 + SOLUTION_TYPE_GENERATIVE_CHAT = 4 class SearchTier(proto.Enum): r"""Tiers of search features. Different tiers might have - different pricing. To learn more, please check the pricing + different pricing. To learn more, check the pricing documentation. Values: diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/types/conversational_search_service.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/types/conversational_search_service.py index 659c2c633020..54f131c0a7a3 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/types/conversational_search_service.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/types/conversational_search_service.py @@ -110,6 +110,11 @@ class ConverseConversationRequest(proto.Message): For more information about filtering including syntax and filter operators, see `Filter `__ + boost_spec (google.cloud.discoveryengine_v1.types.SearchRequest.BoostSpec): + Boost specification to boost certain documents in search + results which may affect the converse response. For more + information on boosting, see + `Boosting `__ """ name: str = proto.Field( @@ -150,6 +155,11 @@ class ConverseConversationRequest(proto.Message): proto.STRING, number=9, ) + boost_spec: search_service.SearchRequest.BoostSpec = proto.Field( + proto.MESSAGE, + number=10, + message=search_service.SearchRequest.BoostSpec, + ) class ConverseConversationResponse(proto.Message): diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/types/data_store.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/types/data_store.py index 44ae9859b5ad..e251290bb8b0 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/types/data_store.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/types/data_store.py @@ -20,7 +20,7 @@ from google.protobuf import timestamp_pb2 # type: ignore import proto # type: ignore -from google.cloud.discoveryengine_v1.types import common +from google.cloud.discoveryengine_v1.types import common, schema __protobuf__ = proto.module( package="google.cloud.discoveryengine.v1", @@ -72,6 +72,23 @@ class DataStore(proto.Message): Output only. Timestamp the [DataStore][google.cloud.discoveryengine.v1.DataStore] was created at. + starting_schema (google.cloud.discoveryengine_v1.types.Schema): + The start schema to use for this + [DataStore][google.cloud.discoveryengine.v1.DataStore] when + provisioning it. If unset, a default vertical specialized + schema will be used. + + This field is only used by [CreateDataStore][] API, and will + be ignored if used in other APIs. This field will be omitted + from all API responses including [CreateDataStore][] API. To + retrieve a schema of a + [DataStore][google.cloud.discoveryengine.v1.DataStore], use + [SchemaService.GetSchema][google.cloud.discoveryengine.v1.SchemaService.GetSchema] + API instead. + + The provided schema will be validated against certain rules + on schema. Learn more from `this + doc `__. """ class ContentConfig(proto.Enum): @@ -127,6 +144,11 @@ class ContentConfig(proto.Enum): number=4, message=timestamp_pb2.Timestamp, ) + starting_schema: schema.Schema = proto.Field( + proto.MESSAGE, + number=28, + message=schema.Schema, + ) __all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/types/document.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/types/document.py index 2577c9910f9a..92a32e596054 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/types/document.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/types/document.py @@ -18,6 +18,7 @@ from typing import MutableMapping, MutableSequence from google.protobuf import struct_pb2 # type: ignore +from google.protobuf import timestamp_pb2 # type: ignore import proto # type: ignore __protobuf__ = proto.module( @@ -83,6 +84,13 @@ class Document(proto.Message): derived_struct_data (google.protobuf.struct_pb2.Struct): Output only. This field is OUTPUT_ONLY. It contains derived data that are not in the original input document. + index_time (google.protobuf.timestamp_pb2.Timestamp): + Output only. The last time the document was indexed. If this + field is set, the document could be returned in search + results. + + This field is OUTPUT_ONLY. If this field is not populated, + it means the document has never been indexed. """ class Content(proto.Message): @@ -183,6 +191,11 @@ class Content(proto.Message): number=6, message=struct_pb2.Struct, ) + index_time: timestamp_pb2.Timestamp = proto.Field( + proto.MESSAGE, + number=13, + message=timestamp_pb2.Timestamp, + ) __all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/types/document_service.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/types/document_service.py index f12c9a517cfa..e795a2c3ec06 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/types/document_service.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/types/document_service.py @@ -17,6 +17,7 @@ from typing import MutableMapping, MutableSequence +from google.protobuf import field_mask_pb2 # type: ignore import proto # type: ignore from google.cloud.discoveryengine_v1.types import document as gcd_document @@ -218,6 +219,10 @@ class UpdateDocumentRequest(proto.Message): found, a new [Document][google.cloud.discoveryengine.v1.Document] will be created. + update_mask (google.protobuf.field_mask_pb2.FieldMask): + Indicates which fields in the provided + imported 'document' to update. If not set, will + by default update all fields. """ document: gcd_document.Document = proto.Field( @@ -229,6 +234,11 @@ class UpdateDocumentRequest(proto.Message): proto.BOOL, number=2, ) + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=3, + message=field_mask_pb2.FieldMask, + ) class DeleteDocumentRequest(proto.Message): diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/types/engine.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/types/engine.py index ac7dd6b42a55..f4082aafa21d 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/types/engine.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/types/engine.py @@ -130,7 +130,7 @@ class SearchEngineConfig(proto.Message): The search feature tier of this engine. Different tiers might have different pricing. To learn more, - please check the pricing documentation. + check the pricing documentation. Defaults to [SearchTier.SEARCH_TIER_STANDARD][google.cloud.discoveryengine.v1.SearchTier.SEARCH_TIER_STANDARD] @@ -180,7 +180,7 @@ class ChatEngineConfig(proto.Message): [EngineService.GetEngine][google.cloud.discoveryengine.v1.EngineService.GetEngine] or [EngineService.ListEngines][google.cloud.discoveryengine.v1.EngineService.ListEngines] - API after engine creation. Please use + API after engine creation. Use [ChatEngineMetadata.dialogflow_agent][google.cloud.discoveryengine.v1.Engine.ChatEngineMetadata.dialogflow_agent] for actual agent association after Engine is created. """ diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/types/import_config.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/types/import_config.py index b05b7026907e..3fd5da2fb960 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/types/import_config.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/types/import_config.py @@ -17,6 +17,7 @@ from typing import MutableMapping, MutableSequence +from google.protobuf import field_mask_pb2 # type: ignore from google.protobuf import timestamp_pb2 # type: ignore from google.rpc import status_pb2 # type: ignore from google.type import date_pb2 # type: ignore @@ -29,6 +30,12 @@ manifest={ "GcsSource", "BigQuerySource", + "SpannerSource", + "BigtableOptions", + "BigtableSource", + "FhirStoreSource", + "CloudSqlSource", + "FirestoreSource", "ImportErrorConfig", "ImportUserEventsRequest", "ImportUserEventsResponse", @@ -73,11 +80,13 @@ class GcsSource(proto.Message): - ``custom``: One custom data JSON per row in arbitrary format that conforms to the defined [Schema][google.cloud.discoveryengine.v1.Schema] of the - data store. This can only be used by Gen App Builder. + data store. This can only be used by the GENERIC Data + Store vertical. - ``csv``: A CSV file with header conforming to the defined [Schema][google.cloud.discoveryengine.v1.Schema] of the data store. Each entry after the header is imported as a - Document. This can only be used by Gen App Builder. + Document. This can only be used by the GENERIC Data Store + vertical. Supported values for user even imports: @@ -147,7 +156,8 @@ class BigQuerySource(proto.Message): - ``custom``: One custom data per row in arbitrary format that conforms to the defined [Schema][google.cloud.discoveryengine.v1.Schema] of the - data store. This can only be used by Gen App Builder. + data store. This can only be used by the GENERIC Data + Store vertical. """ partition_date: date_pb2.Date = proto.Field( @@ -178,6 +188,402 @@ class BigQuerySource(proto.Message): ) +class SpannerSource(proto.Message): + r"""The Spanner source for importing data + + Attributes: + project_id (str): + The project ID that the Spanner source is in + with a length limit of 128 characters. If not + specified, inherits the project ID from the + parent request. + instance_id (str): + Required. The instance ID of the source + Spanner table. + database_id (str): + Required. The database ID of the source + Spanner table. + table_id (str): + Required. The table name of the Spanner + database that needs to be imported. + enable_data_boost (bool): + Whether to apply data boost on Spanner export. Enabling this + option will incur additional cost. More info can be found + `here `__. + """ + + project_id: str = proto.Field( + proto.STRING, + number=1, + ) + instance_id: str = proto.Field( + proto.STRING, + number=2, + ) + database_id: str = proto.Field( + proto.STRING, + number=3, + ) + table_id: str = proto.Field( + proto.STRING, + number=4, + ) + enable_data_boost: bool = proto.Field( + proto.BOOL, + number=5, + ) + + +class BigtableOptions(proto.Message): + r"""The Bigtable Options object that contains information to + support the import. + + Attributes: + key_field_name (str): + The field name used for saving row key value in the + document. The name has to match the pattern + ``[a-zA-Z0-9][a-zA-Z0-9-_]*``. + families (MutableMapping[str, google.cloud.discoveryengine_v1.types.BigtableOptions.BigtableColumnFamily]): + The mapping from family names to an object + that contains column families level information + for the given column family. If a family is not + present in this map it will be ignored. + """ + + class Type(proto.Enum): + r"""The type of values in a Bigtable column or column family. The values + are expected to be encoded using `HBase + Bytes.toBytes `__ + function when the encoding value is set to ``BINARY``. + + Values: + TYPE_UNSPECIFIED (0): + The type is unspecified. + STRING (1): + String type. + NUMBER (2): + Numerical type. + INTEGER (3): + Integer type. + VAR_INTEGER (4): + Variable length integer type. + BIG_NUMERIC (5): + BigDecimal type. + BOOLEAN (6): + Boolean type. + JSON (7): + JSON type. + """ + TYPE_UNSPECIFIED = 0 + STRING = 1 + NUMBER = 2 + INTEGER = 3 + VAR_INTEGER = 4 + BIG_NUMERIC = 5 + BOOLEAN = 6 + JSON = 7 + + class Encoding(proto.Enum): + r"""The encoding mode of a Bigtable column or column family. + + Values: + ENCODING_UNSPECIFIED (0): + The encoding is unspecified. + TEXT (1): + Text encoding. + BINARY (2): + Binary encoding. + """ + ENCODING_UNSPECIFIED = 0 + TEXT = 1 + BINARY = 2 + + class BigtableColumnFamily(proto.Message): + r"""The column family of the Bigtable. + + Attributes: + field_name (str): + The field name to use for this column family in the + document. The name has to match the pattern + ``[a-zA-Z0-9][a-zA-Z0-9-_]*``. If not set, it is parsed from + the family name with best effort. However, due to different + naming patterns, field name collisions could happen, where + parsing behavior is undefined. + encoding (google.cloud.discoveryengine_v1.types.BigtableOptions.Encoding): + The encoding mode of the values when the type is not STRING. + Acceptable encoding values are: + + - ``TEXT``: indicates values are alphanumeric text strings. + - ``BINARY``: indicates values are encoded using + ``HBase Bytes.toBytes`` family of functions. This can be + overridden for a specific column by listing that column + in ``columns`` and specifying an encoding for it. + type_ (google.cloud.discoveryengine_v1.types.BigtableOptions.Type): + The type of values in this column family. The values are + expected to be encoded using ``HBase Bytes.toBytes`` + function when the encoding value is set to ``BINARY``. + columns (MutableSequence[google.cloud.discoveryengine_v1.types.BigtableOptions.BigtableColumn]): + The list of objects that contains column + level information for each column. If a column + is not present in this list it will be ignored. + """ + + field_name: str = proto.Field( + proto.STRING, + number=1, + ) + encoding: "BigtableOptions.Encoding" = proto.Field( + proto.ENUM, + number=2, + enum="BigtableOptions.Encoding", + ) + type_: "BigtableOptions.Type" = proto.Field( + proto.ENUM, + number=3, + enum="BigtableOptions.Type", + ) + columns: MutableSequence[ + "BigtableOptions.BigtableColumn" + ] = proto.RepeatedField( + proto.MESSAGE, + number=4, + message="BigtableOptions.BigtableColumn", + ) + + class BigtableColumn(proto.Message): + r"""The column of the Bigtable. + + Attributes: + qualifier (bytes): + Required. Qualifier of the column. If it + cannot be decoded with utf-8, use a base-64 + encoded string instead. + field_name (str): + The field name to use for this column in the document. The + name has to match the pattern ``[a-zA-Z0-9][a-zA-Z0-9-_]*``. + If not set, it is parsed from the qualifier bytes with best + effort. However, due to different naming patterns, field + name collisions could happen, where parsing behavior is + undefined. + encoding (google.cloud.discoveryengine_v1.types.BigtableOptions.Encoding): + The encoding mode of the values when the type is not + ``STRING``. Acceptable encoding values are: + + - ``TEXT``: indicates values are alphanumeric text strings. + - ``BINARY``: indicates values are encoded using + ``HBase Bytes.toBytes`` family of functions. This can be + overridden for a specific column by listing that column + in ``columns`` and specifying an encoding for it. + type_ (google.cloud.discoveryengine_v1.types.BigtableOptions.Type): + The type of values in this column family. The values are + expected to be encoded using ``HBase Bytes.toBytes`` + function when the encoding value is set to ``BINARY``. + """ + + qualifier: bytes = proto.Field( + proto.BYTES, + number=1, + ) + field_name: str = proto.Field( + proto.STRING, + number=2, + ) + encoding: "BigtableOptions.Encoding" = proto.Field( + proto.ENUM, + number=3, + enum="BigtableOptions.Encoding", + ) + type_: "BigtableOptions.Type" = proto.Field( + proto.ENUM, + number=4, + enum="BigtableOptions.Type", + ) + + key_field_name: str = proto.Field( + proto.STRING, + number=1, + ) + families: MutableMapping[str, BigtableColumnFamily] = proto.MapField( + proto.STRING, + proto.MESSAGE, + number=2, + message=BigtableColumnFamily, + ) + + +class BigtableSource(proto.Message): + r"""The Cloud Bigtable source for importing data. + + Attributes: + project_id (str): + The project ID that the Bigtable source is in + with a length limit of 128 characters. If not + specified, inherits the project ID from the + parent request. + instance_id (str): + Required. The instance ID of the Cloud + Bigtable that needs to be imported. + table_id (str): + Required. The table ID of the Cloud Bigtable + that needs to be imported. + bigtable_options (google.cloud.discoveryengine_v1.types.BigtableOptions): + Required. Bigtable options that contains + information needed when parsing data into typed + structures. For example, column type + annotations. + """ + + project_id: str = proto.Field( + proto.STRING, + number=1, + ) + instance_id: str = proto.Field( + proto.STRING, + number=2, + ) + table_id: str = proto.Field( + proto.STRING, + number=3, + ) + bigtable_options: "BigtableOptions" = proto.Field( + proto.MESSAGE, + number=4, + message="BigtableOptions", + ) + + +class FhirStoreSource(proto.Message): + r"""Cloud FhirStore source import data from. + + Attributes: + fhir_store (str): + Required. The full resource name of the FHIR store to import + data from, in the format of + ``projects/{project}/locations/{location}/datasets/{dataset}/fhirStores/{fhir_store}``. + gcs_staging_dir (str): + Intermediate Cloud Storage directory used for + the import with a length limit of 2,000 + characters. Can be specified if one wants to + have the FhirStore export to a specific Cloud + Storage directory. + """ + + fhir_store: str = proto.Field( + proto.STRING, + number=1, + ) + gcs_staging_dir: str = proto.Field( + proto.STRING, + number=2, + ) + + +class CloudSqlSource(proto.Message): + r"""Cloud SQL source import data from. + + Attributes: + project_id (str): + The project ID that the Cloud SQL source is + in with a length limit of 128 characters. If not + specified, inherits the project ID from the + parent request. + instance_id (str): + Required. The Cloud SQL instance to copy the + data from with a length limit of 256 characters. + database_id (str): + Required. The Cloud SQL database to copy the + data from with a length limit of 256 characters. + table_id (str): + Required. The Cloud SQL table to copy the + data from with a length limit of 256 characters. + gcs_staging_dir (str): + Intermediate Cloud Storage directory used for + the import with a length limit of 2,000 + characters. Can be specified if one wants to + have the Cloud SQL export to a specific Cloud + Storage directory. + + Ensure that the Cloud SQL service account has + the necessary Cloud Storage Admin permissions to + access the specified Cloud Storage directory. + offload (bool): + Option for serverless export. Enabling this option will + incur additional cost. More info can be found + `here `__. + """ + + project_id: str = proto.Field( + proto.STRING, + number=1, + ) + instance_id: str = proto.Field( + proto.STRING, + number=2, + ) + database_id: str = proto.Field( + proto.STRING, + number=3, + ) + table_id: str = proto.Field( + proto.STRING, + number=4, + ) + gcs_staging_dir: str = proto.Field( + proto.STRING, + number=5, + ) + offload: bool = proto.Field( + proto.BOOL, + number=6, + ) + + +class FirestoreSource(proto.Message): + r"""Firestore source import data from. + + Attributes: + project_id (str): + The project ID that the Cloud SQL source is + in with a length limit of 128 characters. If not + specified, inherits the project ID from the + parent request. + database_id (str): + Required. The Firestore database to copy the + data from with a length limit of 256 characters. + collection_id (str): + Required. The Firestore collection to copy + the data from with a length limit of 1,500 + characters. + gcs_staging_dir (str): + Intermediate Cloud Storage directory used for + the import with a length limit of 2,000 + characters. Can be specified if one wants to + have the Firestore export to a specific Cloud + Storage directory. + + Ensure that the Firestore service account has + the necessary Cloud Storage Admin permissions to + access the specified Cloud Storage directory. + """ + + project_id: str = proto.Field( + proto.STRING, + number=1, + ) + database_id: str = proto.Field( + proto.STRING, + number=2, + ) + collection_id: str = proto.Field( + proto.STRING, + number=3, + ) + gcs_staging_dir: str = proto.Field( + proto.STRING, + number=4, + ) + + class ImportErrorConfig(proto.Message): r"""Configuration of destination for Import related errors. @@ -376,6 +782,8 @@ class ImportDocumentsMetadata(proto.Message): failure_count (int): Count of entries that encountered errors while processing. + total_count (int): + Total count of entries that were processed. """ create_time: timestamp_pb2.Timestamp = proto.Field( @@ -396,6 +804,10 @@ class ImportDocumentsMetadata(proto.Message): proto.INT64, number=4, ) + total_count: int = proto.Field( + proto.INT64, + number=5, + ) class ImportDocumentsRequest(proto.Message): @@ -421,6 +833,26 @@ class ImportDocumentsRequest(proto.Message): bigquery_source (google.cloud.discoveryengine_v1.types.BigQuerySource): BigQuery input source. + This field is a member of `oneof`_ ``source``. + fhir_store_source (google.cloud.discoveryengine_v1.types.FhirStoreSource): + FhirStore input source. + + This field is a member of `oneof`_ ``source``. + spanner_source (google.cloud.discoveryengine_v1.types.SpannerSource): + Spanner input source. + + This field is a member of `oneof`_ ``source``. + cloud_sql_source (google.cloud.discoveryengine_v1.types.CloudSqlSource): + Cloud SQL input source. + + This field is a member of `oneof`_ ``source``. + firestore_source (google.cloud.discoveryengine_v1.types.FirestoreSource): + Firestore input source. + + This field is a member of `oneof`_ ``source``. + bigtable_source (google.cloud.discoveryengine_v1.types.BigtableSource): + Cloud Bigtable input source. + This field is a member of `oneof`_ ``source``. parent (str): Required. The parent branch resource name, such as @@ -433,6 +865,10 @@ class ImportDocumentsRequest(proto.Message): The mode of reconciliation between existing documents and the documents to be imported. Defaults to [ReconciliationMode.INCREMENTAL][google.cloud.discoveryengine.v1.ImportDocumentsRequest.ReconciliationMode.INCREMENTAL]. + update_mask (google.protobuf.field_mask_pb2.FieldMask): + Indicates which fields in the provided + imported documents to update. If not set, the + default is to update all fields. auto_generate_ids (bool): Whether to automatically generate IDs for the documents if absent. @@ -450,49 +886,60 @@ class ImportDocumentsRequest(proto.Message): [id_field][google.cloud.discoveryengine.v1.ImportDocumentsRequest.id_field], otherwise, documents without IDs fail to be imported. - Only set this field when using - [GcsSource][google.cloud.discoveryengine.v1.GcsSource] or - [BigQuerySource][google.cloud.discoveryengine.v1.BigQuerySource], - and when - [GcsSource.data_schema][google.cloud.discoveryengine.v1.GcsSource.data_schema] - or - [BigQuerySource.data_schema][google.cloud.discoveryengine.v1.BigQuerySource.data_schema] - is ``custom`` or ``csv``. Otherwise, an INVALID_ARGUMENT - error is thrown. + Supported data sources: + + - [GcsSource][google.cloud.discoveryengine.v1.GcsSource]. + [GcsSource.data_schema][google.cloud.discoveryengine.v1.GcsSource.data_schema] + must be ``custom`` or ``csv``. Otherwise, an + INVALID_ARGUMENT error is thrown. + - [BigQuerySource][google.cloud.discoveryengine.v1.BigQuerySource]. + [BigQuerySource.data_schema][google.cloud.discoveryengine.v1.BigQuerySource.data_schema] + must be ``custom`` or ``csv``. Otherwise, an + INVALID_ARGUMENT error is thrown. + - [SpannerSource][google.cloud.discoveryengine.v1.SpannerSource]. + - [CloudSqlSource][google.cloud.discoveryengine.v1.CloudSqlSource]. + - [FirestoreSource][google.cloud.discoveryengine.v1.FirestoreSource]. + - [BigtableSource][google.cloud.discoveryengine.v1.BigtableSource]. id_field (str): - The field in the Cloud Storage and BigQuery sources that - indicates the unique IDs of the documents. + The field indicates the ID field or column to be used as + unique IDs of the documents. For [GcsSource][google.cloud.discoveryengine.v1.GcsSource] it is the key of the JSON field. For instance, ``my_id`` for - JSON ``{"my_id": "some_uuid"}``. For - [BigQuerySource][google.cloud.discoveryengine.v1.BigQuerySource] - it is the column name of the BigQuery table where the unique - ids are stored. + JSON ``{"my_id": "some_uuid"}``. For others, it may be the + column name of the table where the unique ids are stored. - The values of the JSON field or the BigQuery column are used - as the + The values of the JSON field or the table column are used as + the [Document.id][google.cloud.discoveryengine.v1.Document.id]s. - The JSON field or the BigQuery column must be of string - type, and the values must be set as valid strings conform to + The JSON field or the table column must be of string type, + and the values must be set as valid strings conform to `RFC-1034 `__ with 1-63 characters. Otherwise, documents without valid IDs fail to be imported. - Only set this field when using - [GcsSource][google.cloud.discoveryengine.v1.GcsSource] or - [BigQuerySource][google.cloud.discoveryengine.v1.BigQuerySource], - and when - [GcsSource.data_schema][google.cloud.discoveryengine.v1.GcsSource.data_schema] - or - [BigQuerySource.data_schema][google.cloud.discoveryengine.v1.BigQuerySource.data_schema] - is ``custom``. And only set this field when + Only set this field when [auto_generate_ids][google.cloud.discoveryengine.v1.ImportDocumentsRequest.auto_generate_ids] is unset or set as ``false``. Otherwise, an INVALID_ARGUMENT error is thrown. If it is unset, a default value ``_id`` is used when importing from the allowed data sources. + + Supported data sources: + + - [GcsSource][google.cloud.discoveryengine.v1.GcsSource]. + [GcsSource.data_schema][google.cloud.discoveryengine.v1.GcsSource.data_schema] + must be ``custom`` or ``csv``. Otherwise, an + INVALID_ARGUMENT error is thrown. + - [BigQuerySource][google.cloud.discoveryengine.v1.BigQuerySource]. + [BigQuerySource.data_schema][google.cloud.discoveryengine.v1.BigQuerySource.data_schema] + must be ``custom`` or ``csv``. Otherwise, an + INVALID_ARGUMENT error is thrown. + - [SpannerSource][google.cloud.discoveryengine.v1.SpannerSource]. + - [CloudSqlSource][google.cloud.discoveryengine.v1.CloudSqlSource]. + - [FirestoreSource][google.cloud.discoveryengine.v1.FirestoreSource]. + - [BigtableSource][google.cloud.discoveryengine.v1.BigtableSource]. """ class ReconciliationMode(proto.Enum): @@ -551,6 +998,36 @@ class InlineSource(proto.Message): oneof="source", message="BigQuerySource", ) + fhir_store_source: "FhirStoreSource" = proto.Field( + proto.MESSAGE, + number=10, + oneof="source", + message="FhirStoreSource", + ) + spanner_source: "SpannerSource" = proto.Field( + proto.MESSAGE, + number=11, + oneof="source", + message="SpannerSource", + ) + cloud_sql_source: "CloudSqlSource" = proto.Field( + proto.MESSAGE, + number=12, + oneof="source", + message="CloudSqlSource", + ) + firestore_source: "FirestoreSource" = proto.Field( + proto.MESSAGE, + number=13, + oneof="source", + message="FirestoreSource", + ) + bigtable_source: "BigtableSource" = proto.Field( + proto.MESSAGE, + number=15, + oneof="source", + message="BigtableSource", + ) parent: str = proto.Field( proto.STRING, number=1, @@ -565,6 +1042,11 @@ class InlineSource(proto.Message): number=6, enum=ReconciliationMode, ) + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=7, + message=field_mask_pb2.FieldMask, + ) auto_generate_ids: bool = proto.Field( proto.BOOL, number=8, diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/types/purge_config.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/types/purge_config.py index d8951ffecdbb..6495befb0445 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/types/purge_config.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/types/purge_config.py @@ -110,6 +110,9 @@ class PurgeDocumentsMetadata(proto.Message): failure_count (int): Count of entries that encountered errors while processing. + ignored_count (int): + Count of entries that were ignored as entries + were not found. """ create_time: timestamp_pb2.Timestamp = proto.Field( @@ -130,6 +133,10 @@ class PurgeDocumentsMetadata(proto.Message): proto.INT64, number=4, ) + ignored_count: int = proto.Field( + proto.INT64, + number=5, + ) class PurgeSuggestionDenyListEntriesRequest(proto.Message): diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/types/recommendation_service.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/types/recommendation_service.py new file mode 100644 index 000000000000..690381d27704 --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/types/recommendation_service.py @@ -0,0 +1,287 @@ +# -*- 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 struct_pb2 # type: ignore +import proto # type: ignore + +from google.cloud.discoveryengine_v1.types import document as gcd_document +from google.cloud.discoveryengine_v1.types import user_event as gcd_user_event + +__protobuf__ = proto.module( + package="google.cloud.discoveryengine.v1", + manifest={ + "RecommendRequest", + "RecommendResponse", + }, +) + + +class RecommendRequest(proto.Message): + r"""Request message for Recommend method. + + Attributes: + serving_config (str): + Required. Full resource name of a [ServingConfig][]: + ``projects/*/locations/global/collections/*/engines/*/servingConfigs/*``, + or + ``projects/*/locations/global/collections/*/dataStores/*/servingConfigs/*`` + + One default serving config is created along with your + recommendation engine creation. The engine ID will be used + as the ID of the default serving config. For example, for + Engine + ``projects/*/locations/global/collections/*/engines/my-engine``, + you can use + ``projects/*/locations/global/collections/*/engines/my-engine/servingConfigs/my-engine`` + for your + [RecommendationService.Recommend][google.cloud.discoveryengine.v1.RecommendationService.Recommend] + requests. + user_event (google.cloud.discoveryengine_v1.types.UserEvent): + Required. Context about the user, what they are looking at + and what action they took to trigger the Recommend request. + Note that this user event detail won't be ingested to + userEvent logs. Thus, a separate userEvent write request is + required for event logging. + + Don't set + [UserEvent.user_pseudo_id][google.cloud.discoveryengine.v1.UserEvent.user_pseudo_id] + or + [UserEvent.user_info.user_id][google.cloud.discoveryengine.v1.UserInfo.user_id] + to the same fixed ID for different users. If you are trying + to receive non-personalized recommendations (not + recommended; this can negatively impact model performance), + instead set + [UserEvent.user_pseudo_id][google.cloud.discoveryengine.v1.UserEvent.user_pseudo_id] + to a random unique ID and leave + [UserEvent.user_info.user_id][google.cloud.discoveryengine.v1.UserInfo.user_id] + unset. + page_size (int): + Maximum number of results to return. Set this + property to the number of recommendation results + needed. If zero, the service will choose a + reasonable default. The maximum allowed value is + 100. Values above 100 will be coerced to 100. + filter (str): + Filter for restricting recommendation results with a length + limit of 5,000 characters. Currently, only filter + expressions on the ``filter_tags`` attribute is supported. + + Examples: + + - ``(filter_tags: ANY("Red", "Blue") OR filter_tags: ANY("Hot", "Cold"))`` + - ``(filter_tags: ANY("Red", "Blue")) AND NOT (filter_tags: ANY("Green"))`` + + If ``attributeFilteringSyntax`` is set to true under the + ``params`` field, then attribute-based expressions are + expected instead of the above described tag-based syntax. + Examples: + + - (launguage: ANY("en", "es")) AND NOT (categories: + ANY("Movie")) + - (available: true) AND (launguage: ANY("en", "es")) OR + (categories: ANY("Movie")) + + If your filter blocks all results, the API will return + generic (unfiltered) popular Documents. If you only want + results strictly matching the filters, set + ``strictFiltering`` to True in + [RecommendRequest.params][google.cloud.discoveryengine.v1.RecommendRequest.params] + to receive empty results instead. + + Note that the API will never return + [Document][google.cloud.discoveryengine.v1.Document]s with + ``storageStatus`` of ``EXPIRED`` or ``DELETED`` regardless + of filter choices. + validate_only (bool): + Use validate only mode for this + recommendation query. If set to true, a fake + model will be used that returns arbitrary + Document IDs. Note that the validate only mode + should only be used for testing the API, or if + the model is not ready. + params (MutableMapping[str, google.protobuf.struct_pb2.Value]): + Additional domain specific parameters for the + recommendations. + + Allowed values: + + - ``returnDocument``: Boolean. If set to true, the + associated Document object will be returned in + [RecommendResponse.RecommendationResult.document][google.cloud.discoveryengine.v1.RecommendResponse.RecommendationResult.document]. + - ``returnScore``: Boolean. If set to true, the + recommendation 'score' corresponding to each returned + Document will be set in + [RecommendResponse.RecommendationResult.metadata][google.cloud.discoveryengine.v1.RecommendResponse.RecommendationResult.metadata]. + The given 'score' indicates the probability of a Document + conversion given the user's context and history. + - ``strictFiltering``: Boolean. True by default. If set to + false, the service will return generic (unfiltered) + popular Documents instead of empty if your filter blocks + all recommendation results. + - ``diversityLevel``: String. Default empty. If set to be + non-empty, then it needs to be one of: + + - ``no-diversity`` + - ``low-diversity`` + - ``medium-diversity`` + - ``high-diversity`` + - ``auto-diversity`` This gives request-level control + and adjusts recommendation results based on Document + category. + + - ``attributeFilteringSyntax``: Boolean. False by default. + If set to true, the ``filter`` field is interpreted + according to the new, attribute-based syntax. + user_labels (MutableMapping[str, str]): + The user labels applied to a resource must meet the + following requirements: + + - Each resource can have multiple labels, up to a maximum + of 64. + - Each label must be a key-value pair. + - Keys have a minimum length of 1 character and a maximum + length of 63 characters and cannot be empty. Values can + be empty and have a maximum length of 63 characters. + - Keys and values can contain only lowercase letters, + numeric characters, underscores, and dashes. All + characters must use UTF-8 encoding, and international + characters are allowed. + - The key portion of a label must be unique. However, you + can use the same key with multiple resources. + - Keys must start with a lowercase letter or international + character. + + See `Requirements for + labels `__ + for more details. + """ + + serving_config: str = proto.Field( + proto.STRING, + number=1, + ) + user_event: gcd_user_event.UserEvent = proto.Field( + proto.MESSAGE, + number=2, + message=gcd_user_event.UserEvent, + ) + page_size: int = proto.Field( + proto.INT32, + number=3, + ) + filter: str = proto.Field( + proto.STRING, + number=4, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=5, + ) + params: MutableMapping[str, struct_pb2.Value] = proto.MapField( + proto.STRING, + proto.MESSAGE, + number=6, + message=struct_pb2.Value, + ) + user_labels: MutableMapping[str, str] = proto.MapField( + proto.STRING, + proto.STRING, + number=8, + ) + + +class RecommendResponse(proto.Message): + r"""Response message for Recommend method. + + Attributes: + results (MutableSequence[google.cloud.discoveryengine_v1.types.RecommendResponse.RecommendationResult]): + A list of recommended Documents. The order + represents the ranking (from the most relevant + Document to the least). + attribution_token (str): + A unique attribution token. This should be included in the + [UserEvent][google.cloud.discoveryengine.v1.UserEvent] logs + resulting from this recommendation, which enables accurate + attribution of recommendation model performance. + missing_ids (MutableSequence[str]): + IDs of documents in the request that were + missing from the default Branch associated with + the requested ServingConfig. + validate_only (bool): + True if + [RecommendRequest.validate_only][google.cloud.discoveryengine.v1.RecommendRequest.validate_only] + was set. + """ + + class RecommendationResult(proto.Message): + r"""RecommendationResult represents a generic recommendation + result with associated metadata. + + Attributes: + id (str): + Resource ID of the recommended Document. + document (google.cloud.discoveryengine_v1.types.Document): + Set if ``returnDocument`` is set to true in + [RecommendRequest.params][google.cloud.discoveryengine.v1.RecommendRequest.params]. + metadata (MutableMapping[str, google.protobuf.struct_pb2.Value]): + Additional Document metadata / annotations. + + Possible values: + + - ``score``: Recommendation score in double value. Is set + if ``returnScore`` is set to true in + [RecommendRequest.params][google.cloud.discoveryengine.v1.RecommendRequest.params]. + """ + + id: str = proto.Field( + proto.STRING, + number=1, + ) + document: gcd_document.Document = proto.Field( + proto.MESSAGE, + number=2, + message=gcd_document.Document, + ) + metadata: MutableMapping[str, struct_pb2.Value] = proto.MapField( + proto.STRING, + proto.MESSAGE, + number=3, + message=struct_pb2.Value, + ) + + results: MutableSequence[RecommendationResult] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message=RecommendationResult, + ) + attribution_token: str = proto.Field( + proto.STRING, + number=2, + ) + missing_ids: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=3, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=4, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/types/search_service.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/types/search_service.py index cae7cc12c416..e72f559c6149 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/types/search_service.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/types/search_service.py @@ -59,9 +59,15 @@ class SearchRequest(proto.Message): page_size (int): Maximum number of [Document][google.cloud.discoveryengine.v1.Document]s to - return. If unspecified, defaults to a reasonable value. The - maximum allowed value is 100. Values above 100 are coerced - to 100. + return. The maximum allowed value depends on the data type. + Values above the maximum value are coerced to the maximum + value. + + - Websites with basic indexing: Default ``10``, Maximum + ``25``. + - Websites with advanced indexing: Default ``25``, Maximum + ``50``. + - Other: Default ``50``, Maximum ``100``. If this field is negative, an ``INVALID_ARGUMENT`` is returned. @@ -85,6 +91,9 @@ class SearchRequest(proto.Message): If this field is negative, an ``INVALID_ARGUMENT`` is returned. + data_store_specs (MutableSequence[google.cloud.discoveryengine_v1.types.SearchRequest.DataStoreSpec]): + A list of data store specs to apply on a + search call. filter (str): The filter syntax consists of an expression language for constructing a predicate from one or more fields of the @@ -235,6 +244,22 @@ class ImageQuery(proto.Message): oneof="image", ) + class DataStoreSpec(proto.Message): + r"""A struct to define data stores to filter on in a search call. + + Attributes: + data_store (str): + Required. Full resource name of + [DataStore][google.cloud.discoveryengine.v1.DataStore], such + as + ``projects/{project}/locations/{location}/collections/{collection_id}/dataStores/{data_store_id}``. + """ + + data_store: str = proto.Field( + proto.STRING, + number=1, + ) + class FacetSpec(proto.Message): r"""A facet specification to perform faceted search. @@ -452,9 +477,7 @@ class ConditionBoostSpec(proto.Message): - To boost documents with document ID "doc_1" or "doc_2", and color "Red" or "Blue": - - - (id: ANY("doc_1", "doc_2")) AND (color: - ANY("Red","Blue")) + ``(document_id: ANY("doc_1", "doc_2")) AND (color: ANY("Red", "Blue"))`` boost (float): Strength of the condition boost, which should be in [-1, 1]. Negative boost means demotion. Default is 0.0. @@ -473,7 +496,10 @@ class ConditionBoostSpec(proto.Message): ranking, but it is not blocked out completely. Setting to 0.0 means no boost applied. The boosting - condition is ignored. + condition is ignored. Only one of the (condition, boost) + combination or the boost_control_spec below are set. If both + are set then the global boost is ignored and the more + fine-grained boost_control_spec is applied. """ condition: str = proto.Field( @@ -591,6 +617,9 @@ class ContentSearchSpec(proto.Message): summary_spec (google.cloud.discoveryengine_v1.types.SearchRequest.ContentSearchSpec.SummarySpec): If ``summarySpec`` is not specified, summaries are not included in the search response. + extractive_content_spec (google.cloud.discoveryengine_v1.types.SearchRequest.ContentSearchSpec.ExtractiveContentSpec): + If there is no extractive_content_spec provided, there will + be no extractive answer in the search response. """ class SnippetSpec(proto.Message): @@ -637,7 +666,12 @@ class SummarySpec(proto.Message): ``summaryResultCount``, the summary is generated from all of the results. - At most five results can be used to generate a summary. + At most 10 results for documents mode, or 50 for chunks + mode, can be used to generate a summary. The chunks mode is + used when + [SearchRequest.ContentSearchSpec.search_result_mode][] is + set to + [CHUNKS][SearchRequest.ContentSearchSpec.SearchResultMode.CHUNKS]. include_citations (bool): Specifies whether to include citations in the summary. The default value is ``false``. @@ -694,6 +728,15 @@ class SummarySpec(proto.Message): model_spec (google.cloud.discoveryengine_v1.types.SearchRequest.ContentSearchSpec.SummarySpec.ModelSpec): If specified, the spec will be used to modify the model specification provided to the LLM. + use_semantic_chunks (bool): + If true, answer will be generated from most + relevant chunks from top search results. This + feature will improve summary quality. Note that + with this feature enabled, not all top search + results will be referenced and included in the + reference list, so the citation source index + only points to the search results listed in the + reference list. """ class ModelPromptSpec(proto.Message): @@ -721,11 +764,14 @@ class ModelSpec(proto.Message): Supported values are: - ``stable``: string. Default value when no value is - specified. Uses a generally available, fine-tuned version - of the text-bison@001 model. - - ``preview``: string. (Public preview) Uses a fine-tuned - version of the text-bison@002 model. This model works - only for summaries in English. + specified. Uses a generally available, fine-tuned model. + For more information, see `Answer generation model + versions and + lifecycle `__. + - ``preview``: string. (Public preview) Uses a preview + model. For more information, see `Answer generation model + versions and + lifecycle `__. """ version: str = proto.Field( @@ -765,6 +811,86 @@ class ModelSpec(proto.Message): message="SearchRequest.ContentSearchSpec.SummarySpec.ModelSpec", ) ) + use_semantic_chunks: bool = proto.Field( + proto.BOOL, + number=8, + ) + + class ExtractiveContentSpec(proto.Message): + r"""A specification for configuring the extractive content in a + search response. + + Attributes: + max_extractive_answer_count (int): + The maximum number of extractive answers returned in each + search result. + + An extractive answer is a verbatim answer extracted from the + original document, which provides a precise and contextually + relevant answer to the search query. + + If the number of matching answers is less than the + ``max_extractive_answer_count``, return all of the answers. + Otherwise, return the ``max_extractive_answer_count``. + + At most five answers are returned for each + [SearchResult][google.cloud.discoveryengine.v1.SearchResponse.SearchResult]. + max_extractive_segment_count (int): + The max number of extractive segments returned in each + search result. Only applied if the + [DataStore][google.cloud.discoveryengine.v1.DataStore] is + set to + [DataStore.ContentConfig.CONTENT_REQUIRED][google.cloud.discoveryengine.v1.DataStore.ContentConfig.CONTENT_REQUIRED] + or + [DataStore.solution_types][google.cloud.discoveryengine.v1.DataStore.solution_types] + is + [SOLUTION_TYPE_CHAT][google.cloud.discoveryengine.v1.SolutionType.SOLUTION_TYPE_CHAT]. + + An extractive segment is a text segment extracted from the + original document that is relevant to the search query, and, + in general, more verbose than an extractive answer. The + segment could then be used as input for LLMs to generate + summaries and answers. + + If the number of matching segments is less than + ``max_extractive_segment_count``, return all of the + segments. Otherwise, return the + ``max_extractive_segment_count``. + return_extractive_segment_score (bool): + Specifies whether to return the confidence score from the + extractive segments in each search result. This feature is + available only for new or allowlisted data stores. To + allowlist your data store, contact your Customer Engineer. + The default value is ``false``. + num_previous_segments (int): + Specifies whether to also include the adjacent from each + selected segments. Return at most ``num_previous_segments`` + segments before each selected segments. + num_next_segments (int): + Return at most ``num_next_segments`` segments after each + selected segments. + """ + + max_extractive_answer_count: int = proto.Field( + proto.INT32, + number=1, + ) + max_extractive_segment_count: int = proto.Field( + proto.INT32, + number=2, + ) + return_extractive_segment_score: bool = proto.Field( + proto.BOOL, + number=3, + ) + num_previous_segments: int = proto.Field( + proto.INT32, + number=4, + ) + num_next_segments: int = proto.Field( + proto.INT32, + number=5, + ) snippet_spec: "SearchRequest.ContentSearchSpec.SnippetSpec" = proto.Field( proto.MESSAGE, @@ -776,6 +902,11 @@ class ModelSpec(proto.Message): number=2, message="SearchRequest.ContentSearchSpec.SummarySpec", ) + extractive_content_spec: "SearchRequest.ContentSearchSpec.ExtractiveContentSpec" = proto.Field( + proto.MESSAGE, + number=3, + message="SearchRequest.ContentSearchSpec.ExtractiveContentSpec", + ) serving_config: str = proto.Field( proto.STRING, @@ -806,6 +937,11 @@ class ModelSpec(proto.Message): proto.INT32, number=6, ) + data_store_specs: MutableSequence[DataStoreSpec] = proto.RepeatedField( + proto.MESSAGE, + number=32, + message=DataStoreSpec, + ) filter: str = proto.Field( proto.STRING, number=7, @@ -1178,8 +1314,30 @@ class Reference(proto.Message): ``projects/*/locations/*/collections/*/dataStores/*/branches/*/documents/*``. uri (str): Cloud Storage or HTTP uri for the document. + chunk_contents (MutableSequence[google.cloud.discoveryengine_v1.types.SearchResponse.Summary.Reference.ChunkContent]): + List of cited chunk contents derived from + document content. """ + class ChunkContent(proto.Message): + r"""Chunk content. + + Attributes: + content (str): + Chunk textual content. + page_identifier (str): + Page identifier. + """ + + content: str = proto.Field( + proto.STRING, + number=1, + ) + page_identifier: str = proto.Field( + proto.STRING, + number=2, + ) + title: str = proto.Field( proto.STRING, number=1, @@ -1192,6 +1350,13 @@ class Reference(proto.Message): proto.STRING, number=3, ) + chunk_contents: MutableSequence[ + "SearchResponse.Summary.Reference.ChunkContent" + ] = proto.RepeatedField( + proto.MESSAGE, + number=4, + message="SearchResponse.Summary.Reference.ChunkContent", + ) class SummaryWithMetadata(proto.Message): r"""Summary with metadata information. diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/types/user_event.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/types/user_event.py index 08e1f0e1a887..2c75b91a35b2 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/types/user_event.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1/types/user_event.py @@ -130,13 +130,15 @@ class UserEvent(proto.Message): trigger the event. Highly recommended for user events that are the result of - [RecommendationService.Recommend][]. This field enables - accurate attribution of recommendation model performance. + [RecommendationService.Recommend][google.cloud.discoveryengine.v1.RecommendationService.Recommend]. + This field enables accurate attribution of recommendation + model performance. The value must be one of: - - [RecommendResponse.attribution_token][] for events that - are the result of [RecommendationService.Recommend][]. + - [RecommendResponse.attribution_token][google.cloud.discoveryengine.v1.RecommendResponse.attribution_token] + for events that are the result of + [RecommendationService.Recommend][google.cloud.discoveryengine.v1.RecommendationService.Recommend]. - [SearchResponse.attribution_token][google.cloud.discoveryengine.v1.SearchResponse.attribution_token] for events that are the result of [SearchService.Search][google.cloud.discoveryengine.v1.SearchService.Search]. @@ -145,10 +147,12 @@ class UserEvent(proto.Message): conversion completion back to the event and the particular predict response containing this clicked/purchased product. If user clicks on product K in the recommendation results, - pass [RecommendResponse.attribution_token][] as a URL - parameter to product K's page. When recording events on - product K's page, log the - [RecommendResponse.attribution_token][] to this field. + pass + [RecommendResponse.attribution_token][google.cloud.discoveryengine.v1.RecommendResponse.attribution_token] + as a URL parameter to product K's page. When recording + events on product K's page, log the + [RecommendResponse.attribution_token][google.cloud.discoveryengine.v1.RecommendResponse.attribution_token] + to this field. filter (str): The filter syntax consists of an expression language for constructing a predicate from one or more fields of the @@ -161,9 +165,11 @@ class UserEvent(proto.Message): conforming to https://google.aip.dev/160#filtering. Similarly, for ``view-item-list`` events that are generated - from a [RecommendRequest][], this field may be populated - directly from [RecommendRequest.filter][] conforming to - https://google.aip.dev/160#filtering. + from a + [RecommendRequest][google.cloud.discoveryengine.v1.RecommendRequest], + this field may be populated directly from + [RecommendRequest.filter][google.cloud.discoveryengine.v1.RecommendRequest.filter] + conforming to https://google.aip.dev/160#filtering. The value must be a UTF-8 encoded string with a length limit of 1,000 characters. Otherwise, an ``INVALID_ARGUMENT`` @@ -357,7 +363,7 @@ class PageInfo(proto.Message): To represent full path of category, use '>' sign to separate different hierarchies. If '>' is part of the category name, - please replace it with other character(s). + replace it with other character(s). Category pages include special pages such as sales or promotions. For instance, a special sale page may have the diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/__init__.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/__init__.py index dffac0fccc78..532f236ae202 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/__init__.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/__init__.py @@ -41,6 +41,12 @@ EstimateBillingServiceAsyncClient, EstimateBillingServiceClient, ) +from .services.grounded_generation_service import ( + GroundedGenerationServiceAsyncClient, + GroundedGenerationServiceClient, +) +from .services.project_service import ProjectServiceAsyncClient, ProjectServiceClient +from .services.rank_service import RankServiceAsyncClient, RankServiceClient from .services.recommendation_service import ( RecommendationServiceAsyncClient, RecommendationServiceClient, @@ -65,6 +71,7 @@ ) from .types.acl_config import AclConfig from .types.acl_config_service import GetAclConfigRequest, UpdateAclConfigRequest +from .types.answer import Answer from .types.chunk import Chunk from .types.chunk_service import GetChunkRequest, ListChunksRequest, ListChunksResponse from .types.common import ( @@ -92,14 +99,23 @@ TextInput, ) from .types.conversational_search_service import ( + AnswerQueryRequest, + AnswerQueryResponse, ConverseConversationRequest, ConverseConversationResponse, CreateConversationRequest, + CreateSessionRequest, DeleteConversationRequest, + DeleteSessionRequest, + GetAnswerRequest, GetConversationRequest, + GetSessionRequest, ListConversationsRequest, ListConversationsResponse, + ListSessionsRequest, + ListSessionsResponse, UpdateConversationRequest, + UpdateSessionRequest, ) from .types.data_store import DataStore from .types.data_store_service import ( @@ -114,12 +130,13 @@ UpdateDataStoreRequest, UpdateDocumentProcessingConfigRequest, ) -from .types.document import Document +from .types.document import Document, ProcessedDocument from .types.document_processing_config import DocumentProcessingConfig from .types.document_service import ( CreateDocumentRequest, DeleteDocumentRequest, GetDocumentRequest, + GetProcessedDocumentRequest, ListDocumentsRequest, ListDocumentsResponse, UpdateDocumentRequest, @@ -145,8 +162,19 @@ EstimateDataSizeRequest, EstimateDataSizeResponse, ) +from .types.grounded_generation_service import ( + CheckGroundingRequest, + CheckGroundingResponse, + CheckGroundingSpec, +) +from .types.grounding import FactChunk, GroundingFact from .types.import_config import ( BigQuerySource, + BigtableOptions, + BigtableSource, + CloudSqlSource, + FhirStoreSource, + FirestoreSource, GcsSource, ImportDocumentsMetadata, ImportDocumentsRequest, @@ -158,6 +186,14 @@ ImportUserEventsMetadata, ImportUserEventsRequest, ImportUserEventsResponse, + SpannerSource, +) +from .types.project import Project +from .types.project_service import ( + GetProjectRequest, + ProvisionProjectMetadata, + ProvisionProjectRequest, + ReportConsentChangeRequest, ) from .types.purge_config import ( PurgeDocumentsMetadata, @@ -171,6 +207,7 @@ PurgeUserEventsRequest, PurgeUserEventsResponse, ) +from .types.rank_service import RankingRecord, RankRequest, RankResponse from .types.recommendation_service import RecommendRequest, RecommendResponse from .types.schema import FieldConfig, Schema from .types.schema_service import ( @@ -197,6 +234,7 @@ ListServingConfigsResponse, UpdateServingConfigRequest, ) +from .types.session import Query, Session from .types.site_search_engine import SiteSearchEngine, SiteVerificationInfo, TargetSite from .types.site_search_engine_service import ( BatchCreateTargetSiteMetadata, @@ -248,6 +286,9 @@ "DocumentServiceAsyncClient", "EngineServiceAsyncClient", "EstimateBillingServiceAsyncClient", + "GroundedGenerationServiceAsyncClient", + "ProjectServiceAsyncClient", + "RankServiceAsyncClient", "RecommendationServiceAsyncClient", "SchemaServiceAsyncClient", "SearchServiceAsyncClient", @@ -257,6 +298,9 @@ "UserEventServiceAsyncClient", "AclConfig", "AclConfigServiceClient", + "Answer", + "AnswerQueryRequest", + "AnswerQueryResponse", "BatchCreateTargetSiteMetadata", "BatchCreateTargetSitesRequest", "BatchCreateTargetSitesResponse", @@ -264,8 +308,14 @@ "BatchVerifyTargetSitesRequest", "BatchVerifyTargetSitesResponse", "BigQuerySource", + "BigtableOptions", + "BigtableSource", + "CheckGroundingRequest", + "CheckGroundingResponse", + "CheckGroundingSpec", "Chunk", "ChunkServiceClient", + "CloudSqlSource", "CollectUserEventRequest", "CompleteQueryRequest", "CompleteQueryResponse", @@ -285,6 +335,7 @@ "CreateEngineRequest", "CreateSchemaMetadata", "CreateSchemaRequest", + "CreateSessionRequest", "CreateTargetSiteMetadata", "CreateTargetSiteRequest", "CustomAttribute", @@ -299,6 +350,7 @@ "DeleteEngineRequest", "DeleteSchemaMetadata", "DeleteSchemaRequest", + "DeleteSessionRequest", "DeleteTargetSiteMetadata", "DeleteTargetSiteRequest", "DisableAdvancedSiteSearchMetadata", @@ -319,21 +371,30 @@ "EstimateDataSizeMetadata", "EstimateDataSizeRequest", "EstimateDataSizeResponse", + "FactChunk", "FetchDomainVerificationStatusRequest", "FetchDomainVerificationStatusResponse", + "FhirStoreSource", "FieldConfig", + "FirestoreSource", "GcsSource", "GetAclConfigRequest", + "GetAnswerRequest", "GetChunkRequest", "GetConversationRequest", "GetDataStoreRequest", "GetDocumentProcessingConfigRequest", "GetDocumentRequest", "GetEngineRequest", + "GetProcessedDocumentRequest", + "GetProjectRequest", "GetSchemaRequest", "GetServingConfigRequest", + "GetSessionRequest", "GetSiteSearchEngineRequest", "GetTargetSiteRequest", + "GroundedGenerationServiceClient", + "GroundingFact", "GuidedSearchSpec", "IdpConfig", "ImportDocumentsMetadata", @@ -362,6 +423,8 @@ "ListSchemasResponse", "ListServingConfigsRequest", "ListServingConfigsResponse", + "ListSessionsRequest", + "ListSessionsResponse", "ListTargetSitesRequest", "ListTargetSitesResponse", "MediaInfo", @@ -369,6 +432,11 @@ "PanelInfo", "PauseEngineRequest", "Principal", + "ProcessedDocument", + "Project", + "ProjectServiceClient", + "ProvisionProjectMetadata", + "ProvisionProjectRequest", "PurgeDocumentsMetadata", "PurgeDocumentsRequest", "PurgeDocumentsResponse", @@ -379,6 +447,11 @@ "PurgeUserEventsMetadata", "PurgeUserEventsRequest", "PurgeUserEventsResponse", + "Query", + "RankRequest", + "RankResponse", + "RankServiceClient", + "RankingRecord", "RecommendRequest", "RecommendResponse", "RecommendationServiceClient", @@ -386,6 +459,7 @@ "RecrawlUrisRequest", "RecrawlUrisResponse", "Reply", + "ReportConsentChangeRequest", "ResumeEngineRequest", "Schema", "SchemaServiceClient", @@ -398,10 +472,12 @@ "SearchTuningServiceClient", "ServingConfig", "ServingConfigServiceClient", + "Session", "SiteSearchEngine", "SiteSearchEngineServiceClient", "SiteVerificationInfo", "SolutionType", + "SpannerSource", "SuggestionDenyListEntry", "TargetSite", "TextInput", @@ -421,6 +497,7 @@ "UpdateSchemaMetadata", "UpdateSchemaRequest", "UpdateServingConfigRequest", + "UpdateSessionRequest", "UpdateTargetSiteMetadata", "UpdateTargetSiteRequest", "UserEvent", diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/gapic_metadata.json b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/gapic_metadata.json index 8c6560f8ad4d..e2658930445b 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/gapic_metadata.json +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/gapic_metadata.json @@ -172,6 +172,11 @@ "grpc": { "libraryClient": "ConversationalSearchServiceClient", "rpcs": { + "AnswerQuery": { + "methods": [ + "answer_query" + ] + }, "ConverseConversation": { "methods": [ "converse_conversation" @@ -182,31 +187,66 @@ "create_conversation" ] }, + "CreateSession": { + "methods": [ + "create_session" + ] + }, "DeleteConversation": { "methods": [ "delete_conversation" ] }, + "DeleteSession": { + "methods": [ + "delete_session" + ] + }, + "GetAnswer": { + "methods": [ + "get_answer" + ] + }, "GetConversation": { "methods": [ "get_conversation" ] }, + "GetSession": { + "methods": [ + "get_session" + ] + }, "ListConversations": { "methods": [ "list_conversations" ] }, + "ListSessions": { + "methods": [ + "list_sessions" + ] + }, "UpdateConversation": { "methods": [ "update_conversation" ] + }, + "UpdateSession": { + "methods": [ + "update_session" + ] } } }, "grpc-async": { "libraryClient": "ConversationalSearchServiceAsyncClient", "rpcs": { + "AnswerQuery": { + "methods": [ + "answer_query" + ] + }, "ConverseConversation": { "methods": [ "converse_conversation" @@ -217,31 +257,66 @@ "create_conversation" ] }, + "CreateSession": { + "methods": [ + "create_session" + ] + }, "DeleteConversation": { "methods": [ "delete_conversation" ] }, + "DeleteSession": { + "methods": [ + "delete_session" + ] + }, + "GetAnswer": { + "methods": [ + "get_answer" + ] + }, "GetConversation": { "methods": [ "get_conversation" ] }, + "GetSession": { + "methods": [ + "get_session" + ] + }, "ListConversations": { "methods": [ "list_conversations" ] }, + "ListSessions": { + "methods": [ + "list_sessions" + ] + }, "UpdateConversation": { "methods": [ "update_conversation" ] + }, + "UpdateSession": { + "methods": [ + "update_session" + ] } } }, "rest": { "libraryClient": "ConversationalSearchServiceClient", "rpcs": { + "AnswerQuery": { + "methods": [ + "answer_query" + ] + }, "ConverseConversation": { "methods": [ "converse_conversation" @@ -252,25 +327,55 @@ "create_conversation" ] }, + "CreateSession": { + "methods": [ + "create_session" + ] + }, "DeleteConversation": { "methods": [ "delete_conversation" ] }, + "DeleteSession": { + "methods": [ + "delete_session" + ] + }, + "GetAnswer": { + "methods": [ + "get_answer" + ] + }, "GetConversation": { "methods": [ "get_conversation" ] }, + "GetSession": { + "methods": [ + "get_session" + ] + }, "ListConversations": { "methods": [ "list_conversations" ] }, + "ListSessions": { + "methods": [ + "list_sessions" + ] + }, "UpdateConversation": { "methods": [ "update_conversation" ] + }, + "UpdateSession": { + "methods": [ + "update_session" + ] } } } @@ -420,6 +525,11 @@ "get_document" ] }, + "GetProcessedDocument": { + "methods": [ + "get_processed_document" + ] + }, "ImportDocuments": { "methods": [ "import_documents" @@ -460,6 +570,11 @@ "get_document" ] }, + "GetProcessedDocument": { + "methods": [ + "get_processed_document" + ] + }, "ImportDocuments": { "methods": [ "import_documents" @@ -500,6 +615,11 @@ "get_document" ] }, + "GetProcessedDocument": { + "methods": [ + "get_processed_document" + ] + }, "ImportDocuments": { "methods": [ "import_documents" @@ -697,6 +817,138 @@ } } }, + "GroundedGenerationService": { + "clients": { + "grpc": { + "libraryClient": "GroundedGenerationServiceClient", + "rpcs": { + "CheckGrounding": { + "methods": [ + "check_grounding" + ] + } + } + }, + "grpc-async": { + "libraryClient": "GroundedGenerationServiceAsyncClient", + "rpcs": { + "CheckGrounding": { + "methods": [ + "check_grounding" + ] + } + } + }, + "rest": { + "libraryClient": "GroundedGenerationServiceClient", + "rpcs": { + "CheckGrounding": { + "methods": [ + "check_grounding" + ] + } + } + } + } + }, + "ProjectService": { + "clients": { + "grpc": { + "libraryClient": "ProjectServiceClient", + "rpcs": { + "GetProject": { + "methods": [ + "get_project" + ] + }, + "ProvisionProject": { + "methods": [ + "provision_project" + ] + }, + "ReportConsentChange": { + "methods": [ + "report_consent_change" + ] + } + } + }, + "grpc-async": { + "libraryClient": "ProjectServiceAsyncClient", + "rpcs": { + "GetProject": { + "methods": [ + "get_project" + ] + }, + "ProvisionProject": { + "methods": [ + "provision_project" + ] + }, + "ReportConsentChange": { + "methods": [ + "report_consent_change" + ] + } + } + }, + "rest": { + "libraryClient": "ProjectServiceClient", + "rpcs": { + "GetProject": { + "methods": [ + "get_project" + ] + }, + "ProvisionProject": { + "methods": [ + "provision_project" + ] + }, + "ReportConsentChange": { + "methods": [ + "report_consent_change" + ] + } + } + } + } + }, + "RankService": { + "clients": { + "grpc": { + "libraryClient": "RankServiceClient", + "rpcs": { + "Rank": { + "methods": [ + "rank" + ] + } + } + }, + "grpc-async": { + "libraryClient": "RankServiceAsyncClient", + "rpcs": { + "Rank": { + "methods": [ + "rank" + ] + } + } + }, + "rest": { + "libraryClient": "RankServiceClient", + "rpcs": { + "Rank": { + "methods": [ + "rank" + ] + } + } + } + } + }, "RecommendationService": { "clients": { "grpc": { diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/acl_config_service/transports/rest.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/acl_config_service/transports/rest.py index 4f516e5b7554..38a3b6d8ef63 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/acl_config_service/transports/rest.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/acl_config_service/transports/rest.py @@ -551,6 +551,10 @@ def __call__( "method": "get", "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*/operations/*}", }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/evaluations/*/operations/*}", + }, { "method": "get", "uri": "/v1alpha/{name=projects/*/locations/*/operations/*}", diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/chunk_service/transports/rest.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/chunk_service/transports/rest.py index 2f791c760cba..41341880aa7d 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/chunk_service/transports/rest.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/chunk_service/transports/rest.py @@ -556,6 +556,10 @@ def __call__( "method": "get", "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*/operations/*}", }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/evaluations/*/operations/*}", + }, { "method": "get", "uri": "/v1alpha/{name=projects/*/locations/*/operations/*}", diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/completion_service/transports/rest.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/completion_service/transports/rest.py index 36b146494576..22ef00f28f3c 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/completion_service/transports/rest.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/completion_service/transports/rest.py @@ -382,6 +382,10 @@ def operations_client(self) -> operations_v1.AbstractOperationsClient: "method": "get", "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*/operations/*}", }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/evaluations/*/operations/*}", + }, { "method": "get", "uri": "/v1alpha/{name=projects/*/locations/*/operations/*}", @@ -885,6 +889,10 @@ def __call__( "method": "get", "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*/operations/*}", }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/evaluations/*/operations/*}", + }, { "method": "get", "uri": "/v1alpha/{name=projects/*/locations/*/operations/*}", diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/conversational_search_service/async_client.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/conversational_search_service/async_client.py index d3f990718786..3036a2827a53 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/conversational_search_service/async_client.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/conversational_search_service/async_client.py @@ -55,7 +55,10 @@ search_service, ) from google.cloud.discoveryengine_v1alpha.types import conversation as gcd_conversation +from google.cloud.discoveryengine_v1alpha.types import answer from google.cloud.discoveryengine_v1alpha.types import conversation +from google.cloud.discoveryengine_v1alpha.types import session +from google.cloud.discoveryengine_v1alpha.types import session as gcd_session from .client import ConversationalSearchServiceClient from .transports.base import DEFAULT_CLIENT_INFO, ConversationalSearchServiceTransport @@ -76,6 +79,10 @@ class ConversationalSearchServiceAsyncClient: ) _DEFAULT_UNIVERSE = ConversationalSearchServiceClient._DEFAULT_UNIVERSE + answer_path = staticmethod(ConversationalSearchServiceClient.answer_path) + parse_answer_path = staticmethod( + ConversationalSearchServiceClient.parse_answer_path + ) chunk_path = staticmethod(ConversationalSearchServiceClient.chunk_path) parse_chunk_path = staticmethod(ConversationalSearchServiceClient.parse_chunk_path) conversation_path = staticmethod( @@ -98,6 +105,10 @@ class ConversationalSearchServiceAsyncClient: parse_serving_config_path = staticmethod( ConversationalSearchServiceClient.parse_serving_config_path ) + session_path = staticmethod(ConversationalSearchServiceClient.session_path) + parse_session_path = staticmethod( + ConversationalSearchServiceClient.parse_session_path + ) common_billing_account_path = staticmethod( ConversationalSearchServiceClient.common_billing_account_path ) @@ -989,6 +1000,766 @@ async def sample_list_conversations(): # Done; return the response. return response + async def answer_query( + self, + request: Optional[ + Union[conversational_search_service.AnswerQueryRequest, dict] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> conversational_search_service.AnswerQueryResponse: + r"""Answer query method. + + .. 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 discoveryengine_v1alpha + + async def sample_answer_query(): + # Create a client + client = discoveryengine_v1alpha.ConversationalSearchServiceAsyncClient() + + # Initialize request argument(s) + query = discoveryengine_v1alpha.Query() + query.text = "text_value" + + request = discoveryengine_v1alpha.AnswerQueryRequest( + serving_config="serving_config_value", + query=query, + ) + + # Make the request + response = await client.answer_query(request=request) + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.discoveryengine_v1alpha.types.AnswerQueryRequest, dict]]): + The request object. Request message for + [ConversationalSearchService.AnswerQuery][google.cloud.discoveryengine.v1alpha.ConversationalSearchService.AnswerQuery] + 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.cloud.discoveryengine_v1alpha.types.AnswerQueryResponse: + Response message for + [ConversationalSearchService.AnswerQuery][google.cloud.discoveryengine.v1alpha.ConversationalSearchService.AnswerQuery] + method. + + """ + # Create or coerce a protobuf request object. + request = conversational_search_service.AnswerQueryRequest(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.answer_query, + 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( + (("serving_config", request.serving_config),) + ), + ) + + # 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_answer( + self, + request: Optional[ + Union[conversational_search_service.GetAnswerRequest, 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]] = (), + ) -> answer.Answer: + r"""Gets a Answer. + + .. 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 discoveryengine_v1alpha + + async def sample_get_answer(): + # Create a client + client = discoveryengine_v1alpha.ConversationalSearchServiceAsyncClient() + + # Initialize request argument(s) + request = discoveryengine_v1alpha.GetAnswerRequest( + name="name_value", + ) + + # Make the request + response = await client.get_answer(request=request) + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.discoveryengine_v1alpha.types.GetAnswerRequest, dict]]): + The request object. Request for GetAnswer method. + name (:class:`str`): + Required. The resource name of the Answer to get. + Format: + ``projects/{project_number}/locations/{location_id}/collections/{collection}/engines/{engine_id}/sessions/{session_id}/answers/{answer_id}`` + + 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.discoveryengine_v1alpha.types.Answer: + Defines an answer. + """ + # 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." + ) + + request = conversational_search_service.GetAnswerRequest(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 = gapic_v1.method_async.wrap_method( + self._client._transport.get_answer, + 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 create_session( + self, + request: Optional[ + Union[conversational_search_service.CreateSessionRequest, dict] + ] = None, + *, + parent: Optional[str] = None, + session: Optional[gcd_session.Session] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> gcd_session.Session: + r"""Creates a Session. + + If the [Session][google.cloud.discoveryengine.v1alpha.Session] + to create already exists, an ALREADY_EXISTS error is returned. + + .. 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 discoveryengine_v1alpha + + async def sample_create_session(): + # Create a client + client = discoveryengine_v1alpha.ConversationalSearchServiceAsyncClient() + + # Initialize request argument(s) + request = discoveryengine_v1alpha.CreateSessionRequest( + parent="parent_value", + ) + + # Make the request + response = await client.create_session(request=request) + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.discoveryengine_v1alpha.types.CreateSessionRequest, dict]]): + The request object. Request for CreateSession method. + parent (:class:`str`): + Required. Full resource name of parent data store. + Format: + ``projects/{project_number}/locations/{location_id}/collections/{collection}/dataStores/{data_store_id}`` + + This corresponds to the ``parent`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + session (:class:`google.cloud.discoveryengine_v1alpha.types.Session`): + Required. The session to create. + This corresponds to the ``session`` 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.discoveryengine_v1alpha.types.Session: + External session proto definition. + """ + # 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, session]) + 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." + ) + + request = conversational_search_service.CreateSessionRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if parent is not None: + request.parent = parent + if session is not None: + request.session = session + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method_async.wrap_method( + self._client._transport.create_session, + 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((("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 delete_session( + self, + request: Optional[ + Union[conversational_search_service.DeleteSessionRequest, 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]] = (), + ) -> None: + r"""Deletes a Session. + + If the [Session][google.cloud.discoveryengine.v1alpha.Session] + to delete does not exist, a NOT_FOUND error is returned. + + .. 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 discoveryengine_v1alpha + + async def sample_delete_session(): + # Create a client + client = discoveryengine_v1alpha.ConversationalSearchServiceAsyncClient() + + # Initialize request argument(s) + request = discoveryengine_v1alpha.DeleteSessionRequest( + name="name_value", + ) + + # Make the request + await client.delete_session(request=request) + + Args: + request (Optional[Union[google.cloud.discoveryengine_v1alpha.types.DeleteSessionRequest, dict]]): + The request object. Request for DeleteSession method. + name (:class:`str`): + Required. The resource name of the Session to delete. + Format: + ``projects/{project_number}/locations/{location_id}/collections/{collection}/dataStores/{data_store_id}/sessions/{session_id}`` + + 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. + """ + # 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." + ) + + request = conversational_search_service.DeleteSessionRequest(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 = gapic_v1.method_async.wrap_method( + self._client._transport.delete_session, + 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. + await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + async def update_session( + self, + request: Optional[ + Union[conversational_search_service.UpdateSessionRequest, dict] + ] = None, + *, + session: Optional[gcd_session.Session] = 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]] = (), + ) -> gcd_session.Session: + r"""Updates a Session. + + [Session][google.cloud.discoveryengine.v1alpha.Session] action + type cannot be changed. If the + [Session][google.cloud.discoveryengine.v1alpha.Session] to + update does not exist, a NOT_FOUND error is returned. + + .. 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 discoveryengine_v1alpha + + async def sample_update_session(): + # Create a client + client = discoveryengine_v1alpha.ConversationalSearchServiceAsyncClient() + + # Initialize request argument(s) + request = discoveryengine_v1alpha.UpdateSessionRequest( + ) + + # Make the request + response = await client.update_session(request=request) + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.discoveryengine_v1alpha.types.UpdateSessionRequest, dict]]): + The request object. Request for UpdateSession method. + session (:class:`google.cloud.discoveryengine_v1alpha.types.Session`): + Required. The Session to update. + This corresponds to the ``session`` 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 + [Session][google.cloud.discoveryengine.v1alpha.Session] + to update. The following are NOT supported: + + - [Session.name][google.cloud.discoveryengine.v1alpha.Session.name] + + 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.discoveryengine_v1alpha.types.Session: + External session proto definition. + """ + # 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([session, 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." + ) + + request = conversational_search_service.UpdateSessionRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if session is not None: + request.session = session + 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 = gapic_v1.method_async.wrap_method( + self._client._transport.update_session, + 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( + (("session.name", request.session.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_session( + self, + request: Optional[ + Union[conversational_search_service.GetSessionRequest, 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]] = (), + ) -> session.Session: + r"""Gets a Session. + + .. 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 discoveryengine_v1alpha + + async def sample_get_session(): + # Create a client + client = discoveryengine_v1alpha.ConversationalSearchServiceAsyncClient() + + # Initialize request argument(s) + request = discoveryengine_v1alpha.GetSessionRequest( + name="name_value", + ) + + # Make the request + response = await client.get_session(request=request) + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.discoveryengine_v1alpha.types.GetSessionRequest, dict]]): + The request object. Request for GetSession method. + name (:class:`str`): + Required. The resource name of the Session to get. + Format: + ``projects/{project_number}/locations/{location_id}/collections/{collection}/dataStores/{data_store_id}/sessions/{session_id}`` + + 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.discoveryengine_v1alpha.types.Session: + External session proto definition. + """ + # 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." + ) + + request = conversational_search_service.GetSessionRequest(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 = gapic_v1.method_async.wrap_method( + self._client._transport.get_session, + 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 list_sessions( + self, + request: Optional[ + Union[conversational_search_service.ListSessionsRequest, 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]] = (), + ) -> pagers.ListSessionsAsyncPager: + r"""Lists all Sessions by their parent + [DataStore][google.cloud.discoveryengine.v1alpha.DataStore]. + + .. 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 discoveryengine_v1alpha + + async def sample_list_sessions(): + # Create a client + client = discoveryengine_v1alpha.ConversationalSearchServiceAsyncClient() + + # Initialize request argument(s) + request = discoveryengine_v1alpha.ListSessionsRequest( + parent="parent_value", + ) + + # Make the request + page_result = client.list_sessions(request=request) + + # Handle the response + async for response in page_result: + print(response) + + Args: + request (Optional[Union[google.cloud.discoveryengine_v1alpha.types.ListSessionsRequest, dict]]): + The request object. Request for ListSessions method. + parent (:class:`str`): + Required. The data store resource name. Format: + ``projects/{project_number}/locations/{location_id}/collections/{collection}/dataStores/{data_store_id}`` + + 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.discoveryengine_v1alpha.services.conversational_search_service.pagers.ListSessionsAsyncPager: + Response for ListSessions method. + + Iterating over this object will yield + results and resolve additional pages + automatically. + + """ + # 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." + ) + + request = conversational_search_service.ListSessionsRequest(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 = gapic_v1.method_async.wrap_method( + self._client._transport.list_sessions, + 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((("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, + ) + + # This method is paged; wrap the response in a pager, which provides + # an `__aiter__` convenience method. + response = pagers.ListSessionsAsyncPager( + method=rpc, + request=request, + response=response, + metadata=metadata, + ) + + # Done; return the response. + return response + async def list_operations( self, request: Optional[operations_pb2.ListOperationsRequest] = None, diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/conversational_search_service/client.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/conversational_search_service/client.py index fb1ca94ae1f4..e443853f31b6 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/conversational_search_service/client.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/conversational_search_service/client.py @@ -60,7 +60,10 @@ search_service, ) from google.cloud.discoveryengine_v1alpha.types import conversation as gcd_conversation +from google.cloud.discoveryengine_v1alpha.types import answer from google.cloud.discoveryengine_v1alpha.types import conversation +from google.cloud.discoveryengine_v1alpha.types import session +from google.cloud.discoveryengine_v1alpha.types import session as gcd_session from .transports.base import DEFAULT_CLIENT_INFO, ConversationalSearchServiceTransport from .transports.grpc import ConversationalSearchServiceGrpcTransport @@ -198,6 +201,32 @@ def transport(self) -> ConversationalSearchServiceTransport: """ return self._transport + @staticmethod + def answer_path( + project: str, + location: str, + data_store: str, + session: str, + answer: str, + ) -> str: + """Returns a fully-qualified answer string.""" + return "projects/{project}/locations/{location}/dataStores/{data_store}/sessions/{session}/answers/{answer}".format( + project=project, + location=location, + data_store=data_store, + session=session, + answer=answer, + ) + + @staticmethod + def parse_answer_path(path: str) -> Dict[str, str]: + """Parses a answer path into its component segments.""" + m = re.match( + r"^projects/(?P.+?)/locations/(?P.+?)/dataStores/(?P.+?)/sessions/(?P.+?)/answers/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + @staticmethod def chunk_path( project: str, @@ -322,6 +351,30 @@ def parse_serving_config_path(path: str) -> Dict[str, str]: ) return m.groupdict() if m else {} + @staticmethod + def session_path( + project: str, + location: str, + data_store: str, + session: str, + ) -> str: + """Returns a fully-qualified session string.""" + return "projects/{project}/locations/{location}/dataStores/{data_store}/sessions/{session}".format( + project=project, + location=location, + data_store=data_store, + session=session, + ) + + @staticmethod + def parse_session_path(path: str) -> Dict[str, str]: + """Parses a session path into its component segments.""" + m = re.match( + r"^projects/(?P.+?)/locations/(?P.+?)/dataStores/(?P.+?)/sessions/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + @staticmethod def common_billing_account_path( billing_account: str, @@ -1495,6 +1548,767 @@ def sample_list_conversations(): # Done; return the response. return response + def answer_query( + self, + request: Optional[ + Union[conversational_search_service.AnswerQueryRequest, dict] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> conversational_search_service.AnswerQueryResponse: + r"""Answer query method. + + .. 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 discoveryengine_v1alpha + + def sample_answer_query(): + # Create a client + client = discoveryengine_v1alpha.ConversationalSearchServiceClient() + + # Initialize request argument(s) + query = discoveryengine_v1alpha.Query() + query.text = "text_value" + + request = discoveryengine_v1alpha.AnswerQueryRequest( + serving_config="serving_config_value", + query=query, + ) + + # Make the request + response = client.answer_query(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.discoveryengine_v1alpha.types.AnswerQueryRequest, dict]): + The request object. Request message for + [ConversationalSearchService.AnswerQuery][google.cloud.discoveryengine.v1alpha.ConversationalSearchService.AnswerQuery] + 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.cloud.discoveryengine_v1alpha.types.AnswerQueryResponse: + Response message for + [ConversationalSearchService.AnswerQuery][google.cloud.discoveryengine.v1alpha.ConversationalSearchService.AnswerQuery] + method. + + """ + # Create or coerce a protobuf request object. + # Minor optimization to avoid making a copy if the user passes + # in a conversational_search_service.AnswerQueryRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance(request, conversational_search_service.AnswerQueryRequest): + request = conversational_search_service.AnswerQueryRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.answer_query] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("serving_config", request.serving_config),) + ), + ) + + # 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_answer( + self, + request: Optional[ + Union[conversational_search_service.GetAnswerRequest, 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]] = (), + ) -> answer.Answer: + r"""Gets a Answer. + + .. 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 discoveryengine_v1alpha + + def sample_get_answer(): + # Create a client + client = discoveryengine_v1alpha.ConversationalSearchServiceClient() + + # Initialize request argument(s) + request = discoveryengine_v1alpha.GetAnswerRequest( + name="name_value", + ) + + # Make the request + response = client.get_answer(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.discoveryengine_v1alpha.types.GetAnswerRequest, dict]): + The request object. Request for GetAnswer method. + name (str): + Required. The resource name of the Answer to get. + Format: + ``projects/{project_number}/locations/{location_id}/collections/{collection}/engines/{engine_id}/sessions/{session_id}/answers/{answer_id}`` + + 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.discoveryengine_v1alpha.types.Answer: + Defines an answer. + """ + # 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." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a conversational_search_service.GetAnswerRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance(request, conversational_search_service.GetAnswerRequest): + request = conversational_search_service.GetAnswerRequest(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_answer] + + # 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 create_session( + self, + request: Optional[ + Union[conversational_search_service.CreateSessionRequest, dict] + ] = None, + *, + parent: Optional[str] = None, + session: Optional[gcd_session.Session] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> gcd_session.Session: + r"""Creates a Session. + + If the [Session][google.cloud.discoveryengine.v1alpha.Session] + to create already exists, an ALREADY_EXISTS error is returned. + + .. 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 discoveryengine_v1alpha + + def sample_create_session(): + # Create a client + client = discoveryengine_v1alpha.ConversationalSearchServiceClient() + + # Initialize request argument(s) + request = discoveryengine_v1alpha.CreateSessionRequest( + parent="parent_value", + ) + + # Make the request + response = client.create_session(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.discoveryengine_v1alpha.types.CreateSessionRequest, dict]): + The request object. Request for CreateSession method. + parent (str): + Required. Full resource name of parent data store. + Format: + ``projects/{project_number}/locations/{location_id}/collections/{collection}/dataStores/{data_store_id}`` + + This corresponds to the ``parent`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + session (google.cloud.discoveryengine_v1alpha.types.Session): + Required. The session to create. + This corresponds to the ``session`` 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.discoveryengine_v1alpha.types.Session: + External session proto definition. + """ + # 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, session]) + 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." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a conversational_search_service.CreateSessionRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance(request, conversational_search_service.CreateSessionRequest): + request = conversational_search_service.CreateSessionRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if parent is not None: + request.parent = parent + if session is not None: + request.session = session + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.create_session] + + # 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 delete_session( + self, + request: Optional[ + Union[conversational_search_service.DeleteSessionRequest, 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]] = (), + ) -> None: + r"""Deletes a Session. + + If the [Session][google.cloud.discoveryengine.v1alpha.Session] + to delete does not exist, a NOT_FOUND error is returned. + + .. 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 discoveryengine_v1alpha + + def sample_delete_session(): + # Create a client + client = discoveryengine_v1alpha.ConversationalSearchServiceClient() + + # Initialize request argument(s) + request = discoveryengine_v1alpha.DeleteSessionRequest( + name="name_value", + ) + + # Make the request + client.delete_session(request=request) + + Args: + request (Union[google.cloud.discoveryengine_v1alpha.types.DeleteSessionRequest, dict]): + The request object. Request for DeleteSession method. + name (str): + Required. The resource name of the Session to delete. + Format: + ``projects/{project_number}/locations/{location_id}/collections/{collection}/dataStores/{data_store_id}/sessions/{session_id}`` + + 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. + """ + # 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." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a conversational_search_service.DeleteSessionRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance(request, conversational_search_service.DeleteSessionRequest): + request = conversational_search_service.DeleteSessionRequest(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.delete_session] + + # 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. + rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + def update_session( + self, + request: Optional[ + Union[conversational_search_service.UpdateSessionRequest, dict] + ] = None, + *, + session: Optional[gcd_session.Session] = 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]] = (), + ) -> gcd_session.Session: + r"""Updates a Session. + + [Session][google.cloud.discoveryengine.v1alpha.Session] action + type cannot be changed. If the + [Session][google.cloud.discoveryengine.v1alpha.Session] to + update does not exist, a NOT_FOUND error is returned. + + .. 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 discoveryengine_v1alpha + + def sample_update_session(): + # Create a client + client = discoveryengine_v1alpha.ConversationalSearchServiceClient() + + # Initialize request argument(s) + request = discoveryengine_v1alpha.UpdateSessionRequest( + ) + + # Make the request + response = client.update_session(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.discoveryengine_v1alpha.types.UpdateSessionRequest, dict]): + The request object. Request for UpdateSession method. + session (google.cloud.discoveryengine_v1alpha.types.Session): + Required. The Session to update. + This corresponds to the ``session`` 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 + [Session][google.cloud.discoveryengine.v1alpha.Session] + to update. The following are NOT supported: + + - [Session.name][google.cloud.discoveryengine.v1alpha.Session.name] + + 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.discoveryengine_v1alpha.types.Session: + External session proto definition. + """ + # 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([session, 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." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a conversational_search_service.UpdateSessionRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance(request, conversational_search_service.UpdateSessionRequest): + request = conversational_search_service.UpdateSessionRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if session is not None: + request.session = session + 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_session] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("session.name", request.session.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_session( + self, + request: Optional[ + Union[conversational_search_service.GetSessionRequest, 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]] = (), + ) -> session.Session: + r"""Gets a Session. + + .. 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 discoveryengine_v1alpha + + def sample_get_session(): + # Create a client + client = discoveryengine_v1alpha.ConversationalSearchServiceClient() + + # Initialize request argument(s) + request = discoveryengine_v1alpha.GetSessionRequest( + name="name_value", + ) + + # Make the request + response = client.get_session(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.discoveryengine_v1alpha.types.GetSessionRequest, dict]): + The request object. Request for GetSession method. + name (str): + Required. The resource name of the Session to get. + Format: + ``projects/{project_number}/locations/{location_id}/collections/{collection}/dataStores/{data_store_id}/sessions/{session_id}`` + + 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.discoveryengine_v1alpha.types.Session: + External session proto definition. + """ + # 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." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a conversational_search_service.GetSessionRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance(request, conversational_search_service.GetSessionRequest): + request = conversational_search_service.GetSessionRequest(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_session] + + # 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 list_sessions( + self, + request: Optional[ + Union[conversational_search_service.ListSessionsRequest, 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]] = (), + ) -> pagers.ListSessionsPager: + r"""Lists all Sessions by their parent + [DataStore][google.cloud.discoveryengine.v1alpha.DataStore]. + + .. 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 discoveryengine_v1alpha + + def sample_list_sessions(): + # Create a client + client = discoveryengine_v1alpha.ConversationalSearchServiceClient() + + # Initialize request argument(s) + request = discoveryengine_v1alpha.ListSessionsRequest( + parent="parent_value", + ) + + # Make the request + page_result = client.list_sessions(request=request) + + # Handle the response + for response in page_result: + print(response) + + Args: + request (Union[google.cloud.discoveryengine_v1alpha.types.ListSessionsRequest, dict]): + The request object. Request for ListSessions method. + parent (str): + Required. The data store resource name. Format: + ``projects/{project_number}/locations/{location_id}/collections/{collection}/dataStores/{data_store_id}`` + + 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.discoveryengine_v1alpha.services.conversational_search_service.pagers.ListSessionsPager: + Response for ListSessions method. + + Iterating over this object will yield + results and resolve additional pages + automatically. + + """ + # 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." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a conversational_search_service.ListSessionsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance(request, conversational_search_service.ListSessionsRequest): + request = conversational_search_service.ListSessionsRequest(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_sessions] + + # 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, + ) + + # This method is paged; wrap the response in a pager, which provides + # an `__iter__` convenience method. + response = pagers.ListSessionsPager( + method=rpc, + request=request, + response=response, + metadata=metadata, + ) + + # Done; return the response. + return response + def __enter__(self) -> "ConversationalSearchServiceClient": return self diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/conversational_search_service/pagers.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/conversational_search_service/pagers.py index c93d7bd92f1d..f1c90e41be8e 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/conversational_search_service/pagers.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/conversational_search_service/pagers.py @@ -27,6 +27,7 @@ from google.cloud.discoveryengine_v1alpha.types import ( conversation, conversational_search_service, + session, ) @@ -162,3 +163,135 @@ async def async_generator(): def __repr__(self) -> str: return "{0}<{1!r}>".format(self.__class__.__name__, self._response) + + +class ListSessionsPager: + """A pager for iterating through ``list_sessions`` requests. + + This class thinly wraps an initial + :class:`google.cloud.discoveryengine_v1alpha.types.ListSessionsResponse` object, and + provides an ``__iter__`` method to iterate through its + ``sessions`` field. + + If there are more pages, the ``__iter__`` method will make additional + ``ListSessions`` requests and continue to iterate + through the ``sessions`` field on the + corresponding responses. + + All the usual :class:`google.cloud.discoveryengine_v1alpha.types.ListSessionsResponse` + attributes are available on the pager. If multiple requests are made, only + the most recent response is retained, and thus used for attribute lookup. + """ + + def __init__( + self, + method: Callable[..., conversational_search_service.ListSessionsResponse], + request: conversational_search_service.ListSessionsRequest, + response: conversational_search_service.ListSessionsResponse, + *, + metadata: Sequence[Tuple[str, str]] = () + ): + """Instantiate the pager. + + Args: + method (Callable): The method that was originally called, and + which instantiated this pager. + request (google.cloud.discoveryengine_v1alpha.types.ListSessionsRequest): + The initial request object. + response (google.cloud.discoveryengine_v1alpha.types.ListSessionsResponse): + The initial response object. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + """ + self._method = method + self._request = conversational_search_service.ListSessionsRequest(request) + self._response = response + self._metadata = metadata + + def __getattr__(self, name: str) -> Any: + return getattr(self._response, name) + + @property + def pages(self) -> Iterator[conversational_search_service.ListSessionsResponse]: + yield self._response + while self._response.next_page_token: + self._request.page_token = self._response.next_page_token + self._response = self._method(self._request, metadata=self._metadata) + yield self._response + + def __iter__(self) -> Iterator[session.Session]: + for page in self.pages: + yield from page.sessions + + def __repr__(self) -> str: + return "{0}<{1!r}>".format(self.__class__.__name__, self._response) + + +class ListSessionsAsyncPager: + """A pager for iterating through ``list_sessions`` requests. + + This class thinly wraps an initial + :class:`google.cloud.discoveryengine_v1alpha.types.ListSessionsResponse` object, and + provides an ``__aiter__`` method to iterate through its + ``sessions`` field. + + If there are more pages, the ``__aiter__`` method will make additional + ``ListSessions`` requests and continue to iterate + through the ``sessions`` field on the + corresponding responses. + + All the usual :class:`google.cloud.discoveryengine_v1alpha.types.ListSessionsResponse` + attributes are available on the pager. If multiple requests are made, only + the most recent response is retained, and thus used for attribute lookup. + """ + + def __init__( + self, + method: Callable[ + ..., Awaitable[conversational_search_service.ListSessionsResponse] + ], + request: conversational_search_service.ListSessionsRequest, + response: conversational_search_service.ListSessionsResponse, + *, + metadata: Sequence[Tuple[str, str]] = () + ): + """Instantiates the pager. + + Args: + method (Callable): The method that was originally called, and + which instantiated this pager. + request (google.cloud.discoveryengine_v1alpha.types.ListSessionsRequest): + The initial request object. + response (google.cloud.discoveryengine_v1alpha.types.ListSessionsResponse): + The initial response object. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + """ + self._method = method + self._request = conversational_search_service.ListSessionsRequest(request) + self._response = response + self._metadata = metadata + + def __getattr__(self, name: str) -> Any: + return getattr(self._response, name) + + @property + async def pages( + self, + ) -> AsyncIterator[conversational_search_service.ListSessionsResponse]: + yield self._response + while self._response.next_page_token: + self._request.page_token = self._response.next_page_token + self._response = await self._method(self._request, metadata=self._metadata) + yield self._response + + def __aiter__(self) -> AsyncIterator[session.Session]: + async def async_generator(): + async for page in self.pages: + for response in page.sessions: + yield response + + return async_generator() + + def __repr__(self) -> str: + return "{0}<{1!r}>".format(self.__class__.__name__, self._response) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/conversational_search_service/transports/base.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/conversational_search_service/transports/base.py index ad4d74cd03e7..af5dc87f9b81 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/conversational_search_service/transports/base.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/conversational_search_service/transports/base.py @@ -30,7 +30,10 @@ from google.cloud.discoveryengine_v1alpha import gapic_version as package_version from google.cloud.discoveryengine_v1alpha.types import conversation as gcd_conversation from google.cloud.discoveryengine_v1alpha.types import conversational_search_service +from google.cloud.discoveryengine_v1alpha.types import answer from google.cloud.discoveryengine_v1alpha.types import conversation +from google.cloud.discoveryengine_v1alpha.types import session +from google.cloud.discoveryengine_v1alpha.types import session as gcd_session DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( gapic_version=package_version.__version__ @@ -161,6 +164,41 @@ def _prep_wrapped_messages(self, client_info): default_timeout=None, client_info=client_info, ), + self.answer_query: gapic_v1.method.wrap_method( + self.answer_query, + default_timeout=None, + client_info=client_info, + ), + self.get_answer: gapic_v1.method.wrap_method( + self.get_answer, + default_timeout=None, + client_info=client_info, + ), + self.create_session: gapic_v1.method.wrap_method( + self.create_session, + default_timeout=None, + client_info=client_info, + ), + self.delete_session: gapic_v1.method.wrap_method( + self.delete_session, + default_timeout=None, + client_info=client_info, + ), + self.update_session: gapic_v1.method.wrap_method( + self.update_session, + default_timeout=None, + client_info=client_info, + ), + self.get_session: gapic_v1.method.wrap_method( + self.get_session, + default_timeout=None, + client_info=client_info, + ), + self.list_sessions: gapic_v1.method.wrap_method( + self.list_sessions, + default_timeout=None, + client_info=client_info, + ), } def close(self): @@ -232,6 +270,75 @@ def list_conversations( ]: raise NotImplementedError() + @property + def answer_query( + self, + ) -> Callable[ + [conversational_search_service.AnswerQueryRequest], + Union[ + conversational_search_service.AnswerQueryResponse, + Awaitable[conversational_search_service.AnswerQueryResponse], + ], + ]: + raise NotImplementedError() + + @property + def get_answer( + self, + ) -> Callable[ + [conversational_search_service.GetAnswerRequest], + Union[answer.Answer, Awaitable[answer.Answer]], + ]: + raise NotImplementedError() + + @property + def create_session( + self, + ) -> Callable[ + [conversational_search_service.CreateSessionRequest], + Union[gcd_session.Session, Awaitable[gcd_session.Session]], + ]: + raise NotImplementedError() + + @property + def delete_session( + self, + ) -> Callable[ + [conversational_search_service.DeleteSessionRequest], + Union[empty_pb2.Empty, Awaitable[empty_pb2.Empty]], + ]: + raise NotImplementedError() + + @property + def update_session( + self, + ) -> Callable[ + [conversational_search_service.UpdateSessionRequest], + Union[gcd_session.Session, Awaitable[gcd_session.Session]], + ]: + raise NotImplementedError() + + @property + def get_session( + self, + ) -> Callable[ + [conversational_search_service.GetSessionRequest], + Union[session.Session, Awaitable[session.Session]], + ]: + raise NotImplementedError() + + @property + def list_sessions( + self, + ) -> Callable[ + [conversational_search_service.ListSessionsRequest], + Union[ + conversational_search_service.ListSessionsResponse, + Awaitable[conversational_search_service.ListSessionsResponse], + ], + ]: + raise NotImplementedError() + @property def list_operations( self, diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/conversational_search_service/transports/grpc.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/conversational_search_service/transports/grpc.py index eaa583c1eafd..59efd8ce0653 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/conversational_search_service/transports/grpc.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/conversational_search_service/transports/grpc.py @@ -27,7 +27,10 @@ from google.cloud.discoveryengine_v1alpha.types import conversation as gcd_conversation from google.cloud.discoveryengine_v1alpha.types import conversational_search_service +from google.cloud.discoveryengine_v1alpha.types import answer from google.cloud.discoveryengine_v1alpha.types import conversation +from google.cloud.discoveryengine_v1alpha.types import session +from google.cloud.discoveryengine_v1alpha.types import session as gcd_session from .base import DEFAULT_CLIENT_INFO, ConversationalSearchServiceTransport @@ -420,6 +423,212 @@ def list_conversations( ) return self._stubs["list_conversations"] + @property + def answer_query( + self, + ) -> Callable[ + [conversational_search_service.AnswerQueryRequest], + conversational_search_service.AnswerQueryResponse, + ]: + r"""Return a callable for the answer query method over gRPC. + + Answer query method. + + Returns: + Callable[[~.AnswerQueryRequest], + ~.AnswerQueryResponse]: + 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 "answer_query" not in self._stubs: + self._stubs["answer_query"] = self.grpc_channel.unary_unary( + "/google.cloud.discoveryengine.v1alpha.ConversationalSearchService/AnswerQuery", + request_serializer=conversational_search_service.AnswerQueryRequest.serialize, + response_deserializer=conversational_search_service.AnswerQueryResponse.deserialize, + ) + return self._stubs["answer_query"] + + @property + def get_answer( + self, + ) -> Callable[[conversational_search_service.GetAnswerRequest], answer.Answer]: + r"""Return a callable for the get answer method over gRPC. + + Gets a Answer. + + Returns: + Callable[[~.GetAnswerRequest], + ~.Answer]: + 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_answer" not in self._stubs: + self._stubs["get_answer"] = self.grpc_channel.unary_unary( + "/google.cloud.discoveryengine.v1alpha.ConversationalSearchService/GetAnswer", + request_serializer=conversational_search_service.GetAnswerRequest.serialize, + response_deserializer=answer.Answer.deserialize, + ) + return self._stubs["get_answer"] + + @property + def create_session( + self, + ) -> Callable[ + [conversational_search_service.CreateSessionRequest], gcd_session.Session + ]: + r"""Return a callable for the create session method over gRPC. + + Creates a Session. + + If the [Session][google.cloud.discoveryengine.v1alpha.Session] + to create already exists, an ALREADY_EXISTS error is returned. + + Returns: + Callable[[~.CreateSessionRequest], + ~.Session]: + 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 "create_session" not in self._stubs: + self._stubs["create_session"] = self.grpc_channel.unary_unary( + "/google.cloud.discoveryengine.v1alpha.ConversationalSearchService/CreateSession", + request_serializer=conversational_search_service.CreateSessionRequest.serialize, + response_deserializer=gcd_session.Session.deserialize, + ) + return self._stubs["create_session"] + + @property + def delete_session( + self, + ) -> Callable[ + [conversational_search_service.DeleteSessionRequest], empty_pb2.Empty + ]: + r"""Return a callable for the delete session method over gRPC. + + Deletes a Session. + + If the [Session][google.cloud.discoveryengine.v1alpha.Session] + to delete does not exist, a NOT_FOUND error is returned. + + Returns: + Callable[[~.DeleteSessionRequest], + ~.Empty]: + 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 "delete_session" not in self._stubs: + self._stubs["delete_session"] = self.grpc_channel.unary_unary( + "/google.cloud.discoveryengine.v1alpha.ConversationalSearchService/DeleteSession", + request_serializer=conversational_search_service.DeleteSessionRequest.serialize, + response_deserializer=empty_pb2.Empty.FromString, + ) + return self._stubs["delete_session"] + + @property + def update_session( + self, + ) -> Callable[ + [conversational_search_service.UpdateSessionRequest], gcd_session.Session + ]: + r"""Return a callable for the update session method over gRPC. + + Updates a Session. + + [Session][google.cloud.discoveryengine.v1alpha.Session] action + type cannot be changed. If the + [Session][google.cloud.discoveryengine.v1alpha.Session] to + update does not exist, a NOT_FOUND error is returned. + + Returns: + Callable[[~.UpdateSessionRequest], + ~.Session]: + 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_session" not in self._stubs: + self._stubs["update_session"] = self.grpc_channel.unary_unary( + "/google.cloud.discoveryengine.v1alpha.ConversationalSearchService/UpdateSession", + request_serializer=conversational_search_service.UpdateSessionRequest.serialize, + response_deserializer=gcd_session.Session.deserialize, + ) + return self._stubs["update_session"] + + @property + def get_session( + self, + ) -> Callable[[conversational_search_service.GetSessionRequest], session.Session]: + r"""Return a callable for the get session method over gRPC. + + Gets a Session. + + Returns: + Callable[[~.GetSessionRequest], + ~.Session]: + 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_session" not in self._stubs: + self._stubs["get_session"] = self.grpc_channel.unary_unary( + "/google.cloud.discoveryengine.v1alpha.ConversationalSearchService/GetSession", + request_serializer=conversational_search_service.GetSessionRequest.serialize, + response_deserializer=session.Session.deserialize, + ) + return self._stubs["get_session"] + + @property + def list_sessions( + self, + ) -> Callable[ + [conversational_search_service.ListSessionsRequest], + conversational_search_service.ListSessionsResponse, + ]: + r"""Return a callable for the list sessions method over gRPC. + + Lists all Sessions by their parent + [DataStore][google.cloud.discoveryengine.v1alpha.DataStore]. + + Returns: + Callable[[~.ListSessionsRequest], + ~.ListSessionsResponse]: + 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_sessions" not in self._stubs: + self._stubs["list_sessions"] = self.grpc_channel.unary_unary( + "/google.cloud.discoveryengine.v1alpha.ConversationalSearchService/ListSessions", + request_serializer=conversational_search_service.ListSessionsRequest.serialize, + response_deserializer=conversational_search_service.ListSessionsResponse.deserialize, + ) + return self._stubs["list_sessions"] + def close(self): self.grpc_channel.close() diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/conversational_search_service/transports/grpc_asyncio.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/conversational_search_service/transports/grpc_asyncio.py index 63e4525848c9..3e24d0571143 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/conversational_search_service/transports/grpc_asyncio.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/conversational_search_service/transports/grpc_asyncio.py @@ -27,7 +27,10 @@ from google.cloud.discoveryengine_v1alpha.types import conversation as gcd_conversation from google.cloud.discoveryengine_v1alpha.types import conversational_search_service +from google.cloud.discoveryengine_v1alpha.types import answer from google.cloud.discoveryengine_v1alpha.types import conversation +from google.cloud.discoveryengine_v1alpha.types import session +from google.cloud.discoveryengine_v1alpha.types import session as gcd_session from .base import DEFAULT_CLIENT_INFO, ConversationalSearchServiceTransport from .grpc import ConversationalSearchServiceGrpcTransport @@ -426,6 +429,218 @@ def list_conversations( ) return self._stubs["list_conversations"] + @property + def answer_query( + self, + ) -> Callable[ + [conversational_search_service.AnswerQueryRequest], + Awaitable[conversational_search_service.AnswerQueryResponse], + ]: + r"""Return a callable for the answer query method over gRPC. + + Answer query method. + + Returns: + Callable[[~.AnswerQueryRequest], + Awaitable[~.AnswerQueryResponse]]: + 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 "answer_query" not in self._stubs: + self._stubs["answer_query"] = self.grpc_channel.unary_unary( + "/google.cloud.discoveryengine.v1alpha.ConversationalSearchService/AnswerQuery", + request_serializer=conversational_search_service.AnswerQueryRequest.serialize, + response_deserializer=conversational_search_service.AnswerQueryResponse.deserialize, + ) + return self._stubs["answer_query"] + + @property + def get_answer( + self, + ) -> Callable[ + [conversational_search_service.GetAnswerRequest], Awaitable[answer.Answer] + ]: + r"""Return a callable for the get answer method over gRPC. + + Gets a Answer. + + Returns: + Callable[[~.GetAnswerRequest], + Awaitable[~.Answer]]: + 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_answer" not in self._stubs: + self._stubs["get_answer"] = self.grpc_channel.unary_unary( + "/google.cloud.discoveryengine.v1alpha.ConversationalSearchService/GetAnswer", + request_serializer=conversational_search_service.GetAnswerRequest.serialize, + response_deserializer=answer.Answer.deserialize, + ) + return self._stubs["get_answer"] + + @property + def create_session( + self, + ) -> Callable[ + [conversational_search_service.CreateSessionRequest], + Awaitable[gcd_session.Session], + ]: + r"""Return a callable for the create session method over gRPC. + + Creates a Session. + + If the [Session][google.cloud.discoveryengine.v1alpha.Session] + to create already exists, an ALREADY_EXISTS error is returned. + + Returns: + Callable[[~.CreateSessionRequest], + Awaitable[~.Session]]: + 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 "create_session" not in self._stubs: + self._stubs["create_session"] = self.grpc_channel.unary_unary( + "/google.cloud.discoveryengine.v1alpha.ConversationalSearchService/CreateSession", + request_serializer=conversational_search_service.CreateSessionRequest.serialize, + response_deserializer=gcd_session.Session.deserialize, + ) + return self._stubs["create_session"] + + @property + def delete_session( + self, + ) -> Callable[ + [conversational_search_service.DeleteSessionRequest], Awaitable[empty_pb2.Empty] + ]: + r"""Return a callable for the delete session method over gRPC. + + Deletes a Session. + + If the [Session][google.cloud.discoveryengine.v1alpha.Session] + to delete does not exist, a NOT_FOUND error is returned. + + Returns: + Callable[[~.DeleteSessionRequest], + Awaitable[~.Empty]]: + 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 "delete_session" not in self._stubs: + self._stubs["delete_session"] = self.grpc_channel.unary_unary( + "/google.cloud.discoveryengine.v1alpha.ConversationalSearchService/DeleteSession", + request_serializer=conversational_search_service.DeleteSessionRequest.serialize, + response_deserializer=empty_pb2.Empty.FromString, + ) + return self._stubs["delete_session"] + + @property + def update_session( + self, + ) -> Callable[ + [conversational_search_service.UpdateSessionRequest], + Awaitable[gcd_session.Session], + ]: + r"""Return a callable for the update session method over gRPC. + + Updates a Session. + + [Session][google.cloud.discoveryengine.v1alpha.Session] action + type cannot be changed. If the + [Session][google.cloud.discoveryengine.v1alpha.Session] to + update does not exist, a NOT_FOUND error is returned. + + Returns: + Callable[[~.UpdateSessionRequest], + Awaitable[~.Session]]: + 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_session" not in self._stubs: + self._stubs["update_session"] = self.grpc_channel.unary_unary( + "/google.cloud.discoveryengine.v1alpha.ConversationalSearchService/UpdateSession", + request_serializer=conversational_search_service.UpdateSessionRequest.serialize, + response_deserializer=gcd_session.Session.deserialize, + ) + return self._stubs["update_session"] + + @property + def get_session( + self, + ) -> Callable[ + [conversational_search_service.GetSessionRequest], Awaitable[session.Session] + ]: + r"""Return a callable for the get session method over gRPC. + + Gets a Session. + + Returns: + Callable[[~.GetSessionRequest], + Awaitable[~.Session]]: + 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_session" not in self._stubs: + self._stubs["get_session"] = self.grpc_channel.unary_unary( + "/google.cloud.discoveryengine.v1alpha.ConversationalSearchService/GetSession", + request_serializer=conversational_search_service.GetSessionRequest.serialize, + response_deserializer=session.Session.deserialize, + ) + return self._stubs["get_session"] + + @property + def list_sessions( + self, + ) -> Callable[ + [conversational_search_service.ListSessionsRequest], + Awaitable[conversational_search_service.ListSessionsResponse], + ]: + r"""Return a callable for the list sessions method over gRPC. + + Lists all Sessions by their parent + [DataStore][google.cloud.discoveryengine.v1alpha.DataStore]. + + Returns: + Callable[[~.ListSessionsRequest], + Awaitable[~.ListSessionsResponse]]: + 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_sessions" not in self._stubs: + self._stubs["list_sessions"] = self.grpc_channel.unary_unary( + "/google.cloud.discoveryengine.v1alpha.ConversationalSearchService/ListSessions", + request_serializer=conversational_search_service.ListSessionsRequest.serialize, + response_deserializer=conversational_search_service.ListSessionsResponse.deserialize, + ) + return self._stubs["list_sessions"] + def close(self): return self.grpc_channel.close() diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/conversational_search_service/transports/rest.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/conversational_search_service/transports/rest.py index e6b7f8459831..8beb3903b8e6 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/conversational_search_service/transports/rest.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/conversational_search_service/transports/rest.py @@ -42,7 +42,10 @@ from google.cloud.discoveryengine_v1alpha.types import conversation as gcd_conversation from google.cloud.discoveryengine_v1alpha.types import conversational_search_service +from google.cloud.discoveryengine_v1alpha.types import answer from google.cloud.discoveryengine_v1alpha.types import conversation +from google.cloud.discoveryengine_v1alpha.types import session +from google.cloud.discoveryengine_v1alpha.types import session as gcd_session from .base import ConversationalSearchServiceTransport from .base import DEFAULT_CLIENT_INFO as BASE_DEFAULT_CLIENT_INFO @@ -69,6 +72,14 @@ class ConversationalSearchServiceRestInterceptor: .. code-block:: python class MyCustomConversationalSearchServiceInterceptor(ConversationalSearchServiceRestInterceptor): + def pre_answer_query(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_answer_query(self, response): + logging.log(f"Received response: {response}") + return response + def pre_converse_conversation(self, request, metadata): logging.log(f"Received request: {request}") return request, metadata @@ -85,10 +96,30 @@ def post_create_conversation(self, response): logging.log(f"Received response: {response}") return response + def pre_create_session(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_create_session(self, response): + logging.log(f"Received response: {response}") + return response + def pre_delete_conversation(self, request, metadata): logging.log(f"Received request: {request}") return request, metadata + def pre_delete_session(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def pre_get_answer(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_get_answer(self, response): + logging.log(f"Received response: {response}") + return response + def pre_get_conversation(self, request, metadata): logging.log(f"Received request: {request}") return request, metadata @@ -97,6 +128,14 @@ def post_get_conversation(self, response): logging.log(f"Received response: {response}") return response + def pre_get_session(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_get_session(self, response): + logging.log(f"Received response: {response}") + return response + def pre_list_conversations(self, request, metadata): logging.log(f"Received request: {request}") return request, metadata @@ -105,6 +144,14 @@ def post_list_conversations(self, response): logging.log(f"Received response: {response}") return response + def pre_list_sessions(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_list_sessions(self, response): + logging.log(f"Received response: {response}") + return response + def pre_update_conversation(self, request, metadata): logging.log(f"Received request: {request}") return request, metadata @@ -113,12 +160,45 @@ def post_update_conversation(self, response): logging.log(f"Received response: {response}") return response + def pre_update_session(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_update_session(self, response): + logging.log(f"Received response: {response}") + return response + transport = ConversationalSearchServiceRestTransport(interceptor=MyCustomConversationalSearchServiceInterceptor()) client = ConversationalSearchServiceClient(transport=transport) """ + def pre_answer_query( + self, + request: conversational_search_service.AnswerQueryRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[ + conversational_search_service.AnswerQueryRequest, Sequence[Tuple[str, str]] + ]: + """Pre-rpc interceptor for answer_query + + Override in a subclass to manipulate the request or metadata + before they are sent to the ConversationalSearchService server. + """ + return request, metadata + + def post_answer_query( + self, response: conversational_search_service.AnswerQueryResponse + ) -> conversational_search_service.AnswerQueryResponse: + """Post-rpc interceptor for answer_query + + Override in a subclass to manipulate the response + after it is returned by the ConversationalSearchService server but before + it is returned to user code. + """ + return response + def pre_converse_conversation( self, request: conversational_search_service.ConverseConversationRequest, @@ -171,6 +251,29 @@ def post_create_conversation( """ return response + def pre_create_session( + self, + request: conversational_search_service.CreateSessionRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[ + conversational_search_service.CreateSessionRequest, Sequence[Tuple[str, str]] + ]: + """Pre-rpc interceptor for create_session + + Override in a subclass to manipulate the request or metadata + before they are sent to the ConversationalSearchService server. + """ + return request, metadata + + def post_create_session(self, response: gcd_session.Session) -> gcd_session.Session: + """Post-rpc interceptor for create_session + + Override in a subclass to manipulate the response + after it is returned by the ConversationalSearchService server but before + it is returned to user code. + """ + return response + def pre_delete_conversation( self, request: conversational_search_service.DeleteConversationRequest, @@ -186,6 +289,43 @@ def pre_delete_conversation( """ return request, metadata + def pre_delete_session( + self, + request: conversational_search_service.DeleteSessionRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[ + conversational_search_service.DeleteSessionRequest, Sequence[Tuple[str, str]] + ]: + """Pre-rpc interceptor for delete_session + + Override in a subclass to manipulate the request or metadata + before they are sent to the ConversationalSearchService server. + """ + return request, metadata + + def pre_get_answer( + self, + request: conversational_search_service.GetAnswerRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[ + conversational_search_service.GetAnswerRequest, Sequence[Tuple[str, str]] + ]: + """Pre-rpc interceptor for get_answer + + Override in a subclass to manipulate the request or metadata + before they are sent to the ConversationalSearchService server. + """ + return request, metadata + + def post_get_answer(self, response: answer.Answer) -> answer.Answer: + """Post-rpc interceptor for get_answer + + Override in a subclass to manipulate the response + after it is returned by the ConversationalSearchService server but before + it is returned to user code. + """ + return response + def pre_get_conversation( self, request: conversational_search_service.GetConversationRequest, @@ -211,6 +351,29 @@ def post_get_conversation( """ return response + def pre_get_session( + self, + request: conversational_search_service.GetSessionRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[ + conversational_search_service.GetSessionRequest, Sequence[Tuple[str, str]] + ]: + """Pre-rpc interceptor for get_session + + Override in a subclass to manipulate the request or metadata + before they are sent to the ConversationalSearchService server. + """ + return request, metadata + + def post_get_session(self, response: session.Session) -> session.Session: + """Post-rpc interceptor for get_session + + Override in a subclass to manipulate the response + after it is returned by the ConversationalSearchService server but before + it is returned to user code. + """ + return response + def pre_list_conversations( self, request: conversational_search_service.ListConversationsRequest, @@ -237,6 +400,31 @@ def post_list_conversations( """ return response + def pre_list_sessions( + self, + request: conversational_search_service.ListSessionsRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[ + conversational_search_service.ListSessionsRequest, Sequence[Tuple[str, str]] + ]: + """Pre-rpc interceptor for list_sessions + + Override in a subclass to manipulate the request or metadata + before they are sent to the ConversationalSearchService server. + """ + return request, metadata + + def post_list_sessions( + self, response: conversational_search_service.ListSessionsResponse + ) -> conversational_search_service.ListSessionsResponse: + """Post-rpc interceptor for list_sessions + + Override in a subclass to manipulate the response + after it is returned by the ConversationalSearchService server but before + it is returned to user code. + """ + return response + def pre_update_conversation( self, request: conversational_search_service.UpdateConversationRequest, @@ -263,6 +451,29 @@ def post_update_conversation( """ return response + def pre_update_session( + self, + request: conversational_search_service.UpdateSessionRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[ + conversational_search_service.UpdateSessionRequest, Sequence[Tuple[str, str]] + ]: + """Pre-rpc interceptor for update_session + + Override in a subclass to manipulate the request or metadata + before they are sent to the ConversationalSearchService server. + """ + return request, metadata + + def post_update_session(self, response: gcd_session.Session) -> gcd_session.Session: + """Post-rpc interceptor for update_session + + Override in a subclass to manipulate the response + after it is returned by the ConversationalSearchService server but before + it is returned to user code. + """ + return response + def pre_get_operation( self, request: operations_pb2.GetOperationRequest, @@ -406,6 +617,113 @@ def __init__( self._interceptor = interceptor or ConversationalSearchServiceRestInterceptor() self._prep_wrapped_messages(client_info) + class _AnswerQuery(ConversationalSearchServiceRestStub): + def __hash__(self): + return hash("AnswerQuery") + + __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: conversational_search_service.AnswerQueryRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> conversational_search_service.AnswerQueryResponse: + r"""Call the answer query method over HTTP. + + Args: + request (~.conversational_search_service.AnswerQueryRequest): + The request object. Request message for + [ConversationalSearchService.AnswerQuery][google.cloud.discoveryengine.v1alpha.ConversationalSearchService.AnswerQuery] + 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: + ~.conversational_search_service.AnswerQueryResponse: + Response message for + [ConversationalSearchService.AnswerQuery][google.cloud.discoveryengine.v1alpha.ConversationalSearchService.AnswerQuery] + method. + + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "post", + "uri": "/v1alpha/{serving_config=projects/*/locations/*/dataStores/*/servingConfigs/*}:answer", + "body": "*", + }, + { + "method": "post", + "uri": "/v1alpha/{serving_config=projects/*/locations/*/collections/*/dataStores/*/servingConfigs/*}:answer", + "body": "*", + }, + { + "method": "post", + "uri": "/v1alpha/{serving_config=projects/*/locations/*/collections/*/engines/*/servingConfigs/*}:answer", + "body": "*", + }, + ] + request, metadata = self._interceptor.pre_answer_query(request, metadata) + pb_request = conversational_search_service.AnswerQueryRequest.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 = conversational_search_service.AnswerQueryResponse() + pb_resp = conversational_search_service.AnswerQueryResponse.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + resp = self._interceptor.post_answer_query(resp) + return resp + class _ConverseConversation(ConversationalSearchServiceRestStub): def __hash__(self): return hash("ConverseConversation") @@ -628,9 +946,9 @@ def __call__( resp = self._interceptor.post_create_conversation(resp) return resp - class _DeleteConversation(ConversationalSearchServiceRestStub): + class _CreateSession(ConversationalSearchServiceRestStub): def __hash__(self): - return hash("DeleteConversation") + return hash("CreateSession") __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} @@ -644,43 +962,410 @@ def _get_unset_required_fields(cls, message_dict): def __call__( self, - request: conversational_search_service.DeleteConversationRequest, + request: conversational_search_service.CreateSessionRequest, *, retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: Optional[float] = None, metadata: Sequence[Tuple[str, str]] = (), - ): - r"""Call the delete conversation method over HTTP. + ) -> gcd_session.Session: + r"""Call the create session method over HTTP. Args: - request (~.conversational_search_service.DeleteConversationRequest): - The request object. Request for DeleteConversation - method. + request (~.conversational_search_service.CreateSessionRequest): + The request object. Request for CreateSession 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: + ~.gcd_session.Session: + External session proto definition. """ http_options: List[Dict[str, str]] = [ { - "method": "delete", - "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*/conversations/*}", + "method": "post", + "uri": "/v1alpha/{parent=projects/*/locations/*/dataStores/*}/sessions", + "body": "session", }, { - "method": "delete", - "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*/conversations/*}", + "method": "post", + "uri": "/v1alpha/{parent=projects/*/locations/*/collections/*/dataStores/*}/sessions", + "body": "session", + }, + { + "method": "post", + "uri": "/v1alpha/{parent=projects/*/locations/*/collections/*/engines/*}/sessions", + "body": "session", + }, + ] + request, metadata = self._interceptor.pre_create_session(request, metadata) + pb_request = conversational_search_service.CreateSessionRequest.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 = gcd_session.Session() + pb_resp = gcd_session.Session.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + resp = self._interceptor.post_create_session(resp) + return resp + + class _DeleteConversation(ConversationalSearchServiceRestStub): + def __hash__(self): + return hash("DeleteConversation") + + __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: conversational_search_service.DeleteConversationRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ): + r"""Call the delete conversation method over HTTP. + + Args: + request (~.conversational_search_service.DeleteConversationRequest): + The request object. Request for DeleteConversation + 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. + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "delete", + "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*/conversations/*}", + }, + { + "method": "delete", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*/conversations/*}", + }, + { + "method": "delete", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/engines/*/conversations/*}", + }, + ] + request, metadata = self._interceptor.pre_delete_conversation( + request, metadata + ) + pb_request = conversational_search_service.DeleteConversationRequest.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) + + class _DeleteSession(ConversationalSearchServiceRestStub): + def __hash__(self): + return hash("DeleteSession") + + __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: conversational_search_service.DeleteSessionRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ): + r"""Call the delete session method over HTTP. + + Args: + request (~.conversational_search_service.DeleteSessionRequest): + The request object. Request for DeleteSession 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. + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "delete", + "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*/sessions/*}", + }, + { + "method": "delete", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*/sessions/*}", + }, + { + "method": "delete", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/engines/*/sessions/*}", + }, + ] + request, metadata = self._interceptor.pre_delete_session(request, metadata) + pb_request = conversational_search_service.DeleteSessionRequest.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) + + class _GetAnswer(ConversationalSearchServiceRestStub): + def __hash__(self): + return hash("GetAnswer") + + __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: conversational_search_service.GetAnswerRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> answer.Answer: + r"""Call the get answer method over HTTP. + + Args: + request (~.conversational_search_service.GetAnswerRequest): + The request object. Request for GetAnswer 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: + ~.answer.Answer: + Defines an answer. + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*/sessions/*/answers/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*/sessions/*/answers/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/engines/*/sessions/*/answers/*}", + }, + ] + request, metadata = self._interceptor.pre_get_answer(request, metadata) + pb_request = conversational_search_service.GetAnswerRequest.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 = answer.Answer() + pb_resp = answer.Answer.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + resp = self._interceptor.post_get_answer(resp) + return resp + + class _GetConversation(ConversationalSearchServiceRestStub): + def __hash__(self): + return hash("GetConversation") + + __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: conversational_search_service.GetConversationRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> conversation.Conversation: + r"""Call the get conversation method over HTTP. + + Args: + request (~.conversational_search_service.GetConversationRequest): + The request object. Request for GetConversation 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: + ~.conversation.Conversation: + External conversation proto + definition. + + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*/conversations/*}", }, { - "method": "delete", + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*/conversations/*}", + }, + { + "method": "get", "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/engines/*/conversations/*}", }, ] - request, metadata = self._interceptor.pre_delete_conversation( + request, metadata = self._interceptor.pre_get_conversation( request, metadata ) - pb_request = conversational_search_service.DeleteConversationRequest.pb( + pb_request = conversational_search_service.GetConversationRequest.pb( request ) transcoded_request = path_template.transcode(http_options, pb_request) @@ -714,9 +1399,17 @@ def __call__( if response.status_code >= 400: raise core_exceptions.from_http_response(response) - class _GetConversation(ConversationalSearchServiceRestStub): + # Return the response + resp = conversation.Conversation() + pb_resp = conversation.Conversation.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + resp = self._interceptor.post_get_conversation(resp) + return resp + + class _GetSession(ConversationalSearchServiceRestStub): def __hash__(self): - return hash("GetConversation") + return hash("GetSession") __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} @@ -730,17 +1423,17 @@ def _get_unset_required_fields(cls, message_dict): def __call__( self, - request: conversational_search_service.GetConversationRequest, + request: conversational_search_service.GetSessionRequest, *, retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: Optional[float] = None, metadata: Sequence[Tuple[str, str]] = (), - ) -> conversation.Conversation: - r"""Call the get conversation method over HTTP. + ) -> session.Session: + r"""Call the get session method over HTTP. Args: - request (~.conversational_search_service.GetConversationRequest): - The request object. Request for GetConversation method. + request (~.conversational_search_service.GetSessionRequest): + The request object. Request for GetSession method. retry (google.api_core.retry.Retry): Designation of what errors, if any, should be retried. timeout (float): The timeout for this request. @@ -748,32 +1441,26 @@ def __call__( sent along with the request as metadata. Returns: - ~.conversation.Conversation: - External conversation proto - definition. - + ~.session.Session: + External session proto definition. """ http_options: List[Dict[str, str]] = [ { "method": "get", - "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*/conversations/*}", + "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*/sessions/*}", }, { "method": "get", - "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*/conversations/*}", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*/sessions/*}", }, { "method": "get", - "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/engines/*/conversations/*}", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/engines/*/sessions/*}", }, ] - request, metadata = self._interceptor.pre_get_conversation( - request, metadata - ) - pb_request = conversational_search_service.GetConversationRequest.pb( - request - ) + request, metadata = self._interceptor.pre_get_session(request, metadata) + pb_request = conversational_search_service.GetSessionRequest.pb(request) transcoded_request = path_template.transcode(http_options, pb_request) uri = transcoded_request["uri"] @@ -806,11 +1493,11 @@ def __call__( raise core_exceptions.from_http_response(response) # Return the response - resp = conversation.Conversation() - pb_resp = conversation.Conversation.pb(resp) + resp = session.Session() + pb_resp = session.Session.pb(resp) json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) - resp = self._interceptor.post_get_conversation(resp) + resp = self._interceptor.post_get_session(resp) return resp class _ListConversations(ConversationalSearchServiceRestStub): @@ -912,6 +1599,99 @@ def __call__( resp = self._interceptor.post_list_conversations(resp) return resp + class _ListSessions(ConversationalSearchServiceRestStub): + def __hash__(self): + return hash("ListSessions") + + __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: conversational_search_service.ListSessionsRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> conversational_search_service.ListSessionsResponse: + r"""Call the list sessions method over HTTP. + + Args: + request (~.conversational_search_service.ListSessionsRequest): + The request object. Request for ListSessions 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: + ~.conversational_search_service.ListSessionsResponse: + Response for ListSessions method. + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "get", + "uri": "/v1alpha/{parent=projects/*/locations/*/dataStores/*}/sessions", + }, + { + "method": "get", + "uri": "/v1alpha/{parent=projects/*/locations/*/collections/*/dataStores/*}/sessions", + }, + { + "method": "get", + "uri": "/v1alpha/{parent=projects/*/locations/*/collections/*/engines/*}/sessions", + }, + ] + request, metadata = self._interceptor.pre_list_sessions(request, metadata) + pb_request = conversational_search_service.ListSessionsRequest.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 = conversational_search_service.ListSessionsResponse() + pb_resp = conversational_search_service.ListSessionsResponse.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + resp = self._interceptor.post_list_sessions(resp) + return resp + class _UpdateConversation(ConversationalSearchServiceRestStub): def __hash__(self): return hash("UpdateConversation") @@ -1021,6 +1801,119 @@ def __call__( resp = self._interceptor.post_update_conversation(resp) return resp + class _UpdateSession(ConversationalSearchServiceRestStub): + def __hash__(self): + return hash("UpdateSession") + + __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: conversational_search_service.UpdateSessionRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> gcd_session.Session: + r"""Call the update session method over HTTP. + + Args: + request (~.conversational_search_service.UpdateSessionRequest): + The request object. Request for UpdateSession 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: + ~.gcd_session.Session: + External session proto definition. + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "patch", + "uri": "/v1alpha/{session.name=projects/*/locations/*/dataStores/*/sessions/*}", + "body": "session", + }, + { + "method": "patch", + "uri": "/v1alpha/{session.name=projects/*/locations/*/collections/*/dataStores/*/sessions/*}", + "body": "session", + }, + { + "method": "patch", + "uri": "/v1alpha/{session.name=projects/*/locations/*/collections/*/engines/*/sessions/*}", + "body": "session", + }, + ] + request, metadata = self._interceptor.pre_update_session(request, metadata) + pb_request = conversational_search_service.UpdateSessionRequest.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 = gcd_session.Session() + pb_resp = gcd_session.Session.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + resp = self._interceptor.post_update_session(resp) + return resp + + @property + def answer_query( + self, + ) -> Callable[ + [conversational_search_service.AnswerQueryRequest], + conversational_search_service.AnswerQueryResponse, + ]: + # 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._AnswerQuery(self._session, self._host, self._interceptor) # type: ignore + @property def converse_conversation( self, @@ -1043,6 +1936,16 @@ def create_conversation( # In C++ this would require a dynamic_cast return self._CreateConversation(self._session, self._host, self._interceptor) # type: ignore + @property + def create_session( + self, + ) -> Callable[ + [conversational_search_service.CreateSessionRequest], gcd_session.Session + ]: + # 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._CreateSession(self._session, self._host, self._interceptor) # type: ignore + @property def delete_conversation( self, @@ -1053,6 +1956,24 @@ def delete_conversation( # In C++ this would require a dynamic_cast return self._DeleteConversation(self._session, self._host, self._interceptor) # type: ignore + @property + def delete_session( + self, + ) -> Callable[ + [conversational_search_service.DeleteSessionRequest], empty_pb2.Empty + ]: + # 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._DeleteSession(self._session, self._host, self._interceptor) # type: ignore + + @property + def get_answer( + self, + ) -> Callable[[conversational_search_service.GetAnswerRequest], answer.Answer]: + # 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._GetAnswer(self._session, self._host, self._interceptor) # type: ignore + @property def get_conversation( self, @@ -1064,6 +1985,14 @@ def get_conversation( # In C++ this would require a dynamic_cast return self._GetConversation(self._session, self._host, self._interceptor) # type: ignore + @property + def get_session( + self, + ) -> Callable[[conversational_search_service.GetSessionRequest], session.Session]: + # 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._GetSession(self._session, self._host, self._interceptor) # type: ignore + @property def list_conversations( self, @@ -1075,6 +2004,17 @@ def list_conversations( # In C++ this would require a dynamic_cast return self._ListConversations(self._session, self._host, self._interceptor) # type: ignore + @property + def list_sessions( + self, + ) -> Callable[ + [conversational_search_service.ListSessionsRequest], + conversational_search_service.ListSessionsResponse, + ]: + # 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._ListSessions(self._session, self._host, self._interceptor) # type: ignore + @property def update_conversation( self, @@ -1086,6 +2026,16 @@ def update_conversation( # In C++ this would require a dynamic_cast return self._UpdateConversation(self._session, self._host, self._interceptor) # type: ignore + @property + def update_session( + self, + ) -> Callable[ + [conversational_search_service.UpdateSessionRequest], gcd_session.Session + ]: + # 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._UpdateSession(self._session, self._host, self._interceptor) # type: ignore + @property def get_operation(self): return self._GetOperation(self._session, self._host, self._interceptor) # type: ignore @@ -1163,6 +2113,10 @@ def __call__( "method": "get", "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*/operations/*}", }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/evaluations/*/operations/*}", + }, { "method": "get", "uri": "/v1alpha/{name=projects/*/locations/*/operations/*}", diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/data_store_service/transports/rest.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/data_store_service/transports/rest.py index d64ce6962b24..5543795f24f1 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/data_store_service/transports/rest.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/data_store_service/transports/rest.py @@ -511,6 +511,10 @@ def operations_client(self) -> operations_v1.AbstractOperationsClient: "method": "get", "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*/operations/*}", }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/evaluations/*/operations/*}", + }, { "method": "get", "uri": "/v1alpha/{name=projects/*/locations/*/operations/*}", @@ -1450,6 +1454,10 @@ def __call__( "method": "get", "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*/operations/*}", }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/evaluations/*/operations/*}", + }, { "method": "get", "uri": "/v1alpha/{name=projects/*/locations/*/operations/*}", diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/document_service/async_client.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/document_service/async_client.py index cf0b53c800b2..6cae338eb123 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/document_service/async_client.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/document_service/async_client.py @@ -83,6 +83,8 @@ class DocumentServiceAsyncClient: parse_branch_path = staticmethod(DocumentServiceClient.parse_branch_path) document_path = staticmethod(DocumentServiceClient.document_path) parse_document_path = staticmethod(DocumentServiceClient.parse_document_path) + fhir_store_path = staticmethod(DocumentServiceClient.fhir_store_path) + parse_fhir_store_path = staticmethod(DocumentServiceClient.parse_fhir_store_path) common_billing_account_path = staticmethod( DocumentServiceClient.common_billing_account_path ) @@ -1145,6 +1147,128 @@ async def sample_purge_documents(): # Done; return the response. return response + async def get_processed_document( + self, + request: Optional[ + Union[document_service.GetProcessedDocumentRequest, 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]] = (), + ) -> document.ProcessedDocument: + r"""Gets the parsed layout information for a + [Document][google.cloud.discoveryengine.v1alpha.Document]. + + .. 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 discoveryengine_v1alpha + + async def sample_get_processed_document(): + # Create a client + client = discoveryengine_v1alpha.DocumentServiceAsyncClient() + + # Initialize request argument(s) + request = discoveryengine_v1alpha.GetProcessedDocumentRequest( + name="name_value", + processed_document_type="CHUNKED_DOCUMENT", + ) + + # Make the request + response = await client.get_processed_document(request=request) + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.discoveryengine_v1alpha.types.GetProcessedDocumentRequest, dict]]): + The request object. Request message for + [DocumentService.GetDocument][google.cloud.discoveryengine.v1alpha.DocumentService.GetDocument] + method. + name (:class:`str`): + Required. Full resource name of + [Document][google.cloud.discoveryengine.v1alpha.Document], + such as + ``projects/{project}/locations/{location}/collections/{collection}/dataStores/{data_store}/branches/{branch}/documents/{document}``. + + If the caller does not have permission to access the + [Document][google.cloud.discoveryengine.v1alpha.Document], + regardless of whether or not it exists, a + ``PERMISSION_DENIED`` error is returned. + + If the requested + [Document][google.cloud.discoveryengine.v1alpha.Document] + does not exist, a ``NOT_FOUND`` error is returned. + + 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.discoveryengine_v1alpha.types.ProcessedDocument: + Document captures all raw metadata + information of items to be recommended + or searched. + + """ + # 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." + ) + + request = document_service.GetProcessedDocumentRequest(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 = gapic_v1.method_async.wrap_method( + self._client._transport.get_processed_document, + 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 list_operations( self, request: Optional[operations_pb2.ListOperationsRequest] = None, diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/document_service/client.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/document_service/client.py index 208f80f7e439..441460593ca8 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/document_service/client.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/document_service/client.py @@ -249,6 +249,30 @@ def parse_document_path(path: str) -> Dict[str, str]: ) return m.groupdict() if m else {} + @staticmethod + def fhir_store_path( + project: str, + location: str, + dataset: str, + fhir_store: str, + ) -> str: + """Returns a fully-qualified fhir_store string.""" + return "projects/{project}/locations/{location}/datasets/{dataset}/fhirStores/{fhir_store}".format( + project=project, + location=location, + dataset=dataset, + fhir_store=fhir_store, + ) + + @staticmethod + def parse_fhir_store_path(path: str) -> Dict[str, str]: + """Parses a fhir_store path into its component segments.""" + m = re.match( + r"^projects/(?P.+?)/locations/(?P.+?)/datasets/(?P.+?)/fhirStores/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + @staticmethod def common_billing_account_path( billing_account: str, @@ -1577,6 +1601,128 @@ def sample_purge_documents(): # Done; return the response. return response + def get_processed_document( + self, + request: Optional[ + Union[document_service.GetProcessedDocumentRequest, 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]] = (), + ) -> document.ProcessedDocument: + r"""Gets the parsed layout information for a + [Document][google.cloud.discoveryengine.v1alpha.Document]. + + .. 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 discoveryengine_v1alpha + + def sample_get_processed_document(): + # Create a client + client = discoveryengine_v1alpha.DocumentServiceClient() + + # Initialize request argument(s) + request = discoveryengine_v1alpha.GetProcessedDocumentRequest( + name="name_value", + processed_document_type="CHUNKED_DOCUMENT", + ) + + # Make the request + response = client.get_processed_document(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.discoveryengine_v1alpha.types.GetProcessedDocumentRequest, dict]): + The request object. Request message for + [DocumentService.GetDocument][google.cloud.discoveryengine.v1alpha.DocumentService.GetDocument] + method. + name (str): + Required. Full resource name of + [Document][google.cloud.discoveryengine.v1alpha.Document], + such as + ``projects/{project}/locations/{location}/collections/{collection}/dataStores/{data_store}/branches/{branch}/documents/{document}``. + + If the caller does not have permission to access the + [Document][google.cloud.discoveryengine.v1alpha.Document], + regardless of whether or not it exists, a + ``PERMISSION_DENIED`` error is returned. + + If the requested + [Document][google.cloud.discoveryengine.v1alpha.Document] + does not exist, a ``NOT_FOUND`` error is returned. + + 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.discoveryengine_v1alpha.types.ProcessedDocument: + Document captures all raw metadata + information of items to be recommended + or searched. + + """ + # 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." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a document_service.GetProcessedDocumentRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance(request, document_service.GetProcessedDocumentRequest): + request = document_service.GetProcessedDocumentRequest(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_processed_document] + + # 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 __enter__(self) -> "DocumentServiceClient": return self diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/document_service/transports/base.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/document_service/transports/base.py index 4b477f330d04..bb2471bfc1a0 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/document_service/transports/base.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/document_service/transports/base.py @@ -179,6 +179,11 @@ def _prep_wrapped_messages(self, client_info): default_timeout=None, client_info=client_info, ), + self.get_processed_document: gapic_v1.method.wrap_method( + self.get_processed_document, + default_timeout=None, + client_info=client_info, + ), } def close(self): @@ -261,6 +266,15 @@ def purge_documents( ]: raise NotImplementedError() + @property + def get_processed_document( + self, + ) -> Callable[ + [document_service.GetProcessedDocumentRequest], + Union[document.ProcessedDocument, Awaitable[document.ProcessedDocument]], + ]: + raise NotImplementedError() + @property def list_operations( self, diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/document_service/transports/grpc.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/document_service/transports/grpc.py index 2f5881ca1f31..fb4312c79d5c 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/document_service/transports/grpc.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/document_service/transports/grpc.py @@ -468,6 +468,35 @@ def purge_documents( ) return self._stubs["purge_documents"] + @property + def get_processed_document( + self, + ) -> Callable[ + [document_service.GetProcessedDocumentRequest], document.ProcessedDocument + ]: + r"""Return a callable for the get processed document method over gRPC. + + Gets the parsed layout information for a + [Document][google.cloud.discoveryengine.v1alpha.Document]. + + Returns: + Callable[[~.GetProcessedDocumentRequest], + ~.ProcessedDocument]: + 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_processed_document" not in self._stubs: + self._stubs["get_processed_document"] = self.grpc_channel.unary_unary( + "/google.cloud.discoveryengine.v1alpha.DocumentService/GetProcessedDocument", + request_serializer=document_service.GetProcessedDocumentRequest.serialize, + response_deserializer=document.ProcessedDocument.deserialize, + ) + return self._stubs["get_processed_document"] + def close(self): self.grpc_channel.close() diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/document_service/transports/grpc_asyncio.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/document_service/transports/grpc_asyncio.py index 1748888d465f..a7225aa7eb18 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/document_service/transports/grpc_asyncio.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/document_service/transports/grpc_asyncio.py @@ -482,6 +482,36 @@ def purge_documents( ) return self._stubs["purge_documents"] + @property + def get_processed_document( + self, + ) -> Callable[ + [document_service.GetProcessedDocumentRequest], + Awaitable[document.ProcessedDocument], + ]: + r"""Return a callable for the get processed document method over gRPC. + + Gets the parsed layout information for a + [Document][google.cloud.discoveryengine.v1alpha.Document]. + + Returns: + Callable[[~.GetProcessedDocumentRequest], + Awaitable[~.ProcessedDocument]]: + 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_processed_document" not in self._stubs: + self._stubs["get_processed_document"] = self.grpc_channel.unary_unary( + "/google.cloud.discoveryengine.v1alpha.DocumentService/GetProcessedDocument", + request_serializer=document_service.GetProcessedDocumentRequest.serialize, + response_deserializer=document.ProcessedDocument.deserialize, + ) + return self._stubs["get_processed_document"] + def close(self): return self.grpc_channel.close() diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/document_service/transports/rest.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/document_service/transports/rest.py index d5a665e1bae6..ac96353a83ad 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/document_service/transports/rest.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/document_service/transports/rest.py @@ -99,6 +99,14 @@ def post_get_document(self, response): logging.log(f"Received response: {response}") return response + def pre_get_processed_document(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_get_processed_document(self, response): + logging.log(f"Received response: {response}") + return response + def pre_import_documents(self, request, metadata): logging.log(f"Received request: {request}") return request, metadata @@ -193,6 +201,29 @@ def post_get_document(self, response: document.Document) -> document.Document: """ return response + def pre_get_processed_document( + self, + request: document_service.GetProcessedDocumentRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[document_service.GetProcessedDocumentRequest, Sequence[Tuple[str, str]]]: + """Pre-rpc interceptor for get_processed_document + + Override in a subclass to manipulate the request or metadata + before they are sent to the DocumentService server. + """ + return request, metadata + + def post_get_processed_document( + self, response: document.ProcessedDocument + ) -> document.ProcessedDocument: + """Post-rpc interceptor for get_processed_document + + Override in a subclass to manipulate the response + after it is returned by the DocumentService server but before + it is returned to user code. + """ + return response + def pre_import_documents( self, request: import_config.ImportDocumentsRequest, @@ -490,6 +521,10 @@ def operations_client(self) -> operations_v1.AbstractOperationsClient: "method": "get", "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*/operations/*}", }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/evaluations/*/operations/*}", + }, { "method": "get", "uri": "/v1alpha/{name=projects/*/locations/*/operations/*}", @@ -852,6 +887,104 @@ def __call__( resp = self._interceptor.post_get_document(resp) return resp + class _GetProcessedDocument(DocumentServiceRestStub): + def __hash__(self): + return hash("GetProcessedDocument") + + __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = { + "processedDocumentType": {}, + } + + @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: document_service.GetProcessedDocumentRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> document.ProcessedDocument: + r"""Call the get processed document method over HTTP. + + Args: + request (~.document_service.GetProcessedDocumentRequest): + The request object. Request message for + [DocumentService.GetDocument][google.cloud.discoveryengine.v1alpha.DocumentService.GetDocument] + 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: + ~.document.ProcessedDocument: + Document captures all raw metadata + information of items to be recommended + or searched. + + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*/branches/*/documents/*}:getProcessedDocument", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*/branches/*/documents/*}:getProcessedDocument", + }, + ] + request, metadata = self._interceptor.pre_get_processed_document( + request, metadata + ) + pb_request = document_service.GetProcessedDocumentRequest.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 = document.ProcessedDocument() + pb_resp = document.ProcessedDocument.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + resp = self._interceptor.post_get_processed_document(resp) + return resp + class _ImportDocuments(DocumentServiceRestStub): def __hash__(self): return hash("ImportDocuments") @@ -1272,6 +1405,16 @@ def get_document( # In C++ this would require a dynamic_cast return self._GetDocument(self._session, self._host, self._interceptor) # type: ignore + @property + def get_processed_document( + self, + ) -> Callable[ + [document_service.GetProcessedDocumentRequest], document.ProcessedDocument + ]: + # 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._GetProcessedDocument(self._session, self._host, self._interceptor) # type: ignore + @property def import_documents( self, @@ -1383,6 +1526,10 @@ def __call__( "method": "get", "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*/operations/*}", }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/evaluations/*/operations/*}", + }, { "method": "get", "uri": "/v1alpha/{name=projects/*/locations/*/operations/*}", diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/engine_service/async_client.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/engine_service/async_client.py index 6d0d94c10d6c..d4f10b9519d3 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/engine_service/async_client.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/engine_service/async_client.py @@ -298,7 +298,7 @@ async def sample_create_engine(): # Initialize request argument(s) engine = discoveryengine_v1alpha.Engine() engine.display_name = "display_name_value" - engine.solution_type = "SOLUTION_TYPE_CHAT" + engine.solution_type = "SOLUTION_TYPE_GENERATIVE_CHAT" request = discoveryengine_v1alpha.CreateEngineRequest( parent="parent_value", @@ -591,7 +591,7 @@ async def sample_update_engine(): # Initialize request argument(s) engine = discoveryengine_v1alpha.Engine() engine.display_name = "display_name_value" - engine.solution_type = "SOLUTION_TYPE_CHAT" + engine.solution_type = "SOLUTION_TYPE_GENERATIVE_CHAT" request = discoveryengine_v1alpha.UpdateEngineRequest( engine=engine, diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/engine_service/client.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/engine_service/client.py index 530179d20b6c..008db6ce6821 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/engine_service/client.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/engine_service/client.py @@ -733,7 +733,7 @@ def sample_create_engine(): # Initialize request argument(s) engine = discoveryengine_v1alpha.Engine() engine.display_name = "display_name_value" - engine.solution_type = "SOLUTION_TYPE_CHAT" + engine.solution_type = "SOLUTION_TYPE_GENERATIVE_CHAT" request = discoveryengine_v1alpha.CreateEngineRequest( parent="parent_value", @@ -1026,7 +1026,7 @@ def sample_update_engine(): # Initialize request argument(s) engine = discoveryengine_v1alpha.Engine() engine.display_name = "display_name_value" - engine.solution_type = "SOLUTION_TYPE_CHAT" + engine.solution_type = "SOLUTION_TYPE_GENERATIVE_CHAT" request = discoveryengine_v1alpha.UpdateEngineRequest( engine=engine, diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/engine_service/transports/rest.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/engine_service/transports/rest.py index ef302e425d42..fa0ea17da226 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/engine_service/transports/rest.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/engine_service/transports/rest.py @@ -524,6 +524,10 @@ def operations_client(self) -> operations_v1.AbstractOperationsClient: "method": "get", "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*/operations/*}", }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/evaluations/*/operations/*}", + }, { "method": "get", "uri": "/v1alpha/{name=projects/*/locations/*/operations/*}", @@ -1500,6 +1504,10 @@ def __call__( "method": "get", "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*/operations/*}", }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/evaluations/*/operations/*}", + }, { "method": "get", "uri": "/v1alpha/{name=projects/*/locations/*/operations/*}", diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/estimate_billing_service/transports/rest.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/estimate_billing_service/transports/rest.py index d93088ce0bba..30d076310d4d 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/estimate_billing_service/transports/rest.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/estimate_billing_service/transports/rest.py @@ -314,6 +314,10 @@ def operations_client(self) -> operations_v1.AbstractOperationsClient: "method": "get", "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*/operations/*}", }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/evaluations/*/operations/*}", + }, { "method": "get", "uri": "/v1alpha/{name=projects/*/locations/*/operations/*}", @@ -583,6 +587,10 @@ def __call__( "method": "get", "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*/operations/*}", }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/evaluations/*/operations/*}", + }, { "method": "get", "uri": "/v1alpha/{name=projects/*/locations/*/operations/*}", diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/grounded_generation_service/__init__.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/grounded_generation_service/__init__.py new file mode 100644 index 000000000000..8a4c978a5f5e --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/grounded_generation_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 GroundedGenerationServiceAsyncClient +from .client import GroundedGenerationServiceClient + +__all__ = ( + "GroundedGenerationServiceClient", + "GroundedGenerationServiceAsyncClient", +) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/grounded_generation_service/async_client.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/grounded_generation_service/async_client.py new file mode 100644 index 000000000000..7fea5856d352 --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/grounded_generation_service/async_client.py @@ -0,0 +1,488 @@ +# -*- 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 functools +import re +from typing import ( + 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.discoveryengine_v1alpha 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.cloud.discoveryengine_v1alpha.types import ( + grounded_generation_service, + grounding, +) + +from .client import GroundedGenerationServiceClient +from .transports.base import DEFAULT_CLIENT_INFO, GroundedGenerationServiceTransport +from .transports.grpc_asyncio import GroundedGenerationServiceGrpcAsyncIOTransport + + +class GroundedGenerationServiceAsyncClient: + """Service for grounded generation.""" + + _client: GroundedGenerationServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = GroundedGenerationServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = GroundedGenerationServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + GroundedGenerationServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = GroundedGenerationServiceClient._DEFAULT_UNIVERSE + + grounding_config_path = staticmethod( + GroundedGenerationServiceClient.grounding_config_path + ) + parse_grounding_config_path = staticmethod( + GroundedGenerationServiceClient.parse_grounding_config_path + ) + common_billing_account_path = staticmethod( + GroundedGenerationServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + GroundedGenerationServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + GroundedGenerationServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + GroundedGenerationServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + GroundedGenerationServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + GroundedGenerationServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + GroundedGenerationServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + GroundedGenerationServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + GroundedGenerationServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + GroundedGenerationServiceClient.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: + GroundedGenerationServiceAsyncClient: The constructed client. + """ + return GroundedGenerationServiceClient.from_service_account_info.__func__(GroundedGenerationServiceAsyncClient, 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: + GroundedGenerationServiceAsyncClient: The constructed client. + """ + return GroundedGenerationServiceClient.from_service_account_file.__func__(GroundedGenerationServiceAsyncClient, 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 GroundedGenerationServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> GroundedGenerationServiceTransport: + """Returns the transport used by the client instance. + + Returns: + GroundedGenerationServiceTransport: 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 = functools.partial( + type(GroundedGenerationServiceClient).get_transport_class, + type(GroundedGenerationServiceClient), + ) + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Union[str, GroundedGenerationServiceTransport] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the grounded generation 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 (Union[str, ~.GroundedGenerationServiceTransport]): The + transport to use. 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 = GroundedGenerationServiceClient( + credentials=credentials, + transport=transport, + client_options=client_options, + client_info=client_info, + ) + + async def check_grounding( + self, + request: Optional[ + Union[grounded_generation_service.CheckGroundingRequest, dict] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> grounded_generation_service.CheckGroundingResponse: + r"""Performs a grounding check. + + .. 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 discoveryengine_v1alpha + + async def sample_check_grounding(): + # Create a client + client = discoveryengine_v1alpha.GroundedGenerationServiceAsyncClient() + + # Initialize request argument(s) + request = discoveryengine_v1alpha.CheckGroundingRequest( + grounding_config="grounding_config_value", + ) + + # Make the request + response = await client.check_grounding(request=request) + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.discoveryengine_v1alpha.types.CheckGroundingRequest, dict]]): + The request object. Request message for + [GroundedGenerationService.CheckGrounding][google.cloud.discoveryengine.v1alpha.GroundedGenerationService.CheckGrounding] + 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.cloud.discoveryengine_v1alpha.types.CheckGroundingResponse: + Response message for the + [GroundedGenerationService.CheckGrounding][google.cloud.discoveryengine.v1alpha.GroundedGenerationService.CheckGrounding] + method. + + """ + # Create or coerce a protobuf request object. + request = grounded_generation_service.CheckGroundingRequest(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.check_grounding, + 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( + (("grounding_config", request.grounding_config),) + ), + ) + + # 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) -> "GroundedGenerationServiceAsyncClient": + 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__ = ("GroundedGenerationServiceAsyncClient",) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/grounded_generation_service/client.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/grounded_generation_service/client.py new file mode 100644 index 000000000000..562e535e17f0 --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/grounded_generation_service/client.py @@ -0,0 +1,900 @@ +# -*- 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 ( + 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.discoveryengine_v1alpha 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.cloud.discoveryengine_v1alpha.types import ( + grounded_generation_service, + grounding, +) + +from .transports.base import DEFAULT_CLIENT_INFO, GroundedGenerationServiceTransport +from .transports.grpc import GroundedGenerationServiceGrpcTransport +from .transports.grpc_asyncio import GroundedGenerationServiceGrpcAsyncIOTransport +from .transports.rest import GroundedGenerationServiceRestTransport + + +class GroundedGenerationServiceClientMeta(type): + """Metaclass for the GroundedGenerationService 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[GroundedGenerationServiceTransport]] + _transport_registry["grpc"] = GroundedGenerationServiceGrpcTransport + _transport_registry["grpc_asyncio"] = GroundedGenerationServiceGrpcAsyncIOTransport + _transport_registry["rest"] = GroundedGenerationServiceRestTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[GroundedGenerationServiceTransport]: + """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 GroundedGenerationServiceClient(metaclass=GroundedGenerationServiceClientMeta): + """Service for grounded generation.""" + + @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 = "discoveryengine.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "discoveryengine.{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: + GroundedGenerationServiceClient: 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: + GroundedGenerationServiceClient: 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) -> GroundedGenerationServiceTransport: + """Returns the transport used by the client instance. + + Returns: + GroundedGenerationServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def grounding_config_path( + project: str, + location: str, + grounding_config: str, + ) -> str: + """Returns a fully-qualified grounding_config string.""" + return "projects/{project}/locations/{location}/groundingConfigs/{grounding_config}".format( + project=project, + location=location, + grounding_config=grounding_config, + ) + + @staticmethod + def parse_grounding_config_path(path: str) -> Dict[str, str]: + """Parses a grounding_config path into its component segments.""" + m = re.match( + r"^projects/(?P.+?)/locations/(?P.+?)/groundingConfigs/(?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 = GroundedGenerationServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = GroundedGenerationServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + GroundedGenerationServiceClient._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 = GroundedGenerationServiceClient._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 = GroundedGenerationServiceClient._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 GroundedGenerationServiceClient._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, GroundedGenerationServiceTransport]] = None, + client_options: Optional[Union[client_options_lib.ClientOptions, dict]] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the grounded generation 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 (Union[str, GroundedGenerationServiceTransport]): The + transport to use. 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, + ) = GroundedGenerationServiceClient._read_environment_variables() + self._client_cert_source = ( + GroundedGenerationServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = GroundedGenerationServiceClient._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, GroundedGenerationServiceTransport) + if transport_provided: + # transport is a GroundedGenerationServiceTransport 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(GroundedGenerationServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or GroundedGenerationServiceClient._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 = type(self).get_transport_class(cast(str, transport)) + self._transport = Transport( + 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 check_grounding( + self, + request: Optional[ + Union[grounded_generation_service.CheckGroundingRequest, dict] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> grounded_generation_service.CheckGroundingResponse: + r"""Performs a grounding check. + + .. 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 discoveryengine_v1alpha + + def sample_check_grounding(): + # Create a client + client = discoveryengine_v1alpha.GroundedGenerationServiceClient() + + # Initialize request argument(s) + request = discoveryengine_v1alpha.CheckGroundingRequest( + grounding_config="grounding_config_value", + ) + + # Make the request + response = client.check_grounding(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.discoveryengine_v1alpha.types.CheckGroundingRequest, dict]): + The request object. Request message for + [GroundedGenerationService.CheckGrounding][google.cloud.discoveryengine.v1alpha.GroundedGenerationService.CheckGrounding] + 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.cloud.discoveryengine_v1alpha.types.CheckGroundingResponse: + Response message for the + [GroundedGenerationService.CheckGrounding][google.cloud.discoveryengine.v1alpha.GroundedGenerationService.CheckGrounding] + method. + + """ + # Create or coerce a protobuf request object. + # Minor optimization to avoid making a copy if the user passes + # in a grounded_generation_service.CheckGroundingRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance(request, grounded_generation_service.CheckGroundingRequest): + request = grounded_generation_service.CheckGroundingRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.check_grounding] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("grounding_config", request.grounding_config),) + ), + ) + + # 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) -> "GroundedGenerationServiceClient": + 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__ = ("GroundedGenerationServiceClient",) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/grounded_generation_service/transports/__init__.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/grounded_generation_service/transports/__init__.py new file mode 100644 index 000000000000..b2598d761505 --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/grounded_generation_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 GroundedGenerationServiceTransport +from .grpc import GroundedGenerationServiceGrpcTransport +from .grpc_asyncio import GroundedGenerationServiceGrpcAsyncIOTransport +from .rest import ( + GroundedGenerationServiceRestInterceptor, + GroundedGenerationServiceRestTransport, +) + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[GroundedGenerationServiceTransport]] +_transport_registry["grpc"] = GroundedGenerationServiceGrpcTransport +_transport_registry["grpc_asyncio"] = GroundedGenerationServiceGrpcAsyncIOTransport +_transport_registry["rest"] = GroundedGenerationServiceRestTransport + +__all__ = ( + "GroundedGenerationServiceTransport", + "GroundedGenerationServiceGrpcTransport", + "GroundedGenerationServiceGrpcAsyncIOTransport", + "GroundedGenerationServiceRestTransport", + "GroundedGenerationServiceRestInterceptor", +) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/grounded_generation_service/transports/base.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/grounded_generation_service/transports/base.py new file mode 100644 index 000000000000..6fc22370a973 --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/grounded_generation_service/transports/base.py @@ -0,0 +1,185 @@ +# -*- 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.discoveryengine_v1alpha import gapic_version as package_version +from google.cloud.discoveryengine_v1alpha.types import grounded_generation_service + +DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=package_version.__version__ +) + + +class GroundedGenerationServiceTransport(abc.ABC): + """Abstract transport class for GroundedGenerationService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/cloud-platform",) + + DEFAULT_HOST: str = "discoveryengine.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: 'discoveryengine.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 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: + 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.check_grounding: gapic_v1.method.wrap_method( + self.check_grounding, + 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 check_grounding( + self, + ) -> Callable[ + [grounded_generation_service.CheckGroundingRequest], + Union[ + grounded_generation_service.CheckGroundingResponse, + Awaitable[grounded_generation_service.CheckGroundingResponse], + ], + ]: + 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__ = ("GroundedGenerationServiceTransport",) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/grounded_generation_service/transports/grpc.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/grounded_generation_service/transports/grpc.py new file mode 100644 index 000000000000..6fe6f0b69b4b --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/grounded_generation_service/transports/grpc.py @@ -0,0 +1,306 @@ +# -*- 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.discoveryengine_v1alpha.types import grounded_generation_service + +from .base import DEFAULT_CLIENT_INFO, GroundedGenerationServiceTransport + + +class GroundedGenerationServiceGrpcTransport(GroundedGenerationServiceTransport): + """gRPC backend transport for GroundedGenerationService. + + Service for grounded generation. + + 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 = "discoveryengine.googleapis.com", + credentials: Optional[ga_credentials.Credentials] = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + channel: Optional[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: 'discoveryengine.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 ``channel`` 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 ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): 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 ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + 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 channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + 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: + self._grpc_channel = type(self).create_channel( + 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 = "discoveryengine.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 check_grounding( + self, + ) -> Callable[ + [grounded_generation_service.CheckGroundingRequest], + grounded_generation_service.CheckGroundingResponse, + ]: + r"""Return a callable for the check grounding method over gRPC. + + Performs a grounding check. + + Returns: + Callable[[~.CheckGroundingRequest], + ~.CheckGroundingResponse]: + 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 "check_grounding" not in self._stubs: + self._stubs["check_grounding"] = self.grpc_channel.unary_unary( + "/google.cloud.discoveryengine.v1alpha.GroundedGenerationService/CheckGrounding", + request_serializer=grounded_generation_service.CheckGroundingRequest.serialize, + response_deserializer=grounded_generation_service.CheckGroundingResponse.deserialize, + ) + return self._stubs["check_grounding"] + + 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__ = ("GroundedGenerationServiceGrpcTransport",) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/grounded_generation_service/transports/grpc_asyncio.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/grounded_generation_service/transports/grpc_asyncio.py new file mode 100644 index 000000000000..4351e236c863 --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/grounded_generation_service/transports/grpc_asyncio.py @@ -0,0 +1,305 @@ +# -*- 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 gapic_v1, grpc_helpers_async +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.discoveryengine_v1alpha.types import grounded_generation_service + +from .base import DEFAULT_CLIENT_INFO, GroundedGenerationServiceTransport +from .grpc import GroundedGenerationServiceGrpcTransport + + +class GroundedGenerationServiceGrpcAsyncIOTransport(GroundedGenerationServiceTransport): + """gRPC AsyncIO backend transport for GroundedGenerationService. + + Service for grounded generation. + + 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 = "discoveryengine.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`. + This argument is ignored if ``channel`` 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`. + 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 = "discoveryengine.googleapis.com", + credentials: Optional[ga_credentials.Credentials] = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + channel: Optional[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: 'discoveryengine.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 ``channel`` 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 ``channel`` 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[aio.Channel]): A ``Channel`` instance through + which to make calls. + 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 ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + 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 channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + 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: + self._grpc_channel = type(self).create_channel( + 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 check_grounding( + self, + ) -> Callable[ + [grounded_generation_service.CheckGroundingRequest], + Awaitable[grounded_generation_service.CheckGroundingResponse], + ]: + r"""Return a callable for the check grounding method over gRPC. + + Performs a grounding check. + + Returns: + Callable[[~.CheckGroundingRequest], + Awaitable[~.CheckGroundingResponse]]: + 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 "check_grounding" not in self._stubs: + self._stubs["check_grounding"] = self.grpc_channel.unary_unary( + "/google.cloud.discoveryengine.v1alpha.GroundedGenerationService/CheckGrounding", + request_serializer=grounded_generation_service.CheckGroundingRequest.serialize, + response_deserializer=grounded_generation_service.CheckGroundingResponse.deserialize, + ) + return self._stubs["check_grounding"] + + 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__ = ("GroundedGenerationServiceGrpcAsyncIOTransport",) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/grounded_generation_service/transports/rest.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/grounded_generation_service/transports/rest.py new file mode 100644 index 000000000000..04fbcfd4c203 --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/grounded_generation_service/transports/rest.py @@ -0,0 +1,607 @@ +# -*- 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.discoveryengine_v1alpha.types import grounded_generation_service + +from .base import DEFAULT_CLIENT_INFO as BASE_DEFAULT_CLIENT_INFO +from .base import GroundedGenerationServiceTransport + +DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=BASE_DEFAULT_CLIENT_INFO.gapic_version, + grpc_version=None, + rest_version=requests_version, +) + + +class GroundedGenerationServiceRestInterceptor: + """Interceptor for GroundedGenerationService. + + 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 GroundedGenerationServiceRestTransport. + + .. code-block:: python + class MyCustomGroundedGenerationServiceInterceptor(GroundedGenerationServiceRestInterceptor): + def pre_check_grounding(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_check_grounding(self, response): + logging.log(f"Received response: {response}") + return response + + transport = GroundedGenerationServiceRestTransport(interceptor=MyCustomGroundedGenerationServiceInterceptor()) + client = GroundedGenerationServiceClient(transport=transport) + + + """ + + def pre_check_grounding( + self, + request: grounded_generation_service.CheckGroundingRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[ + grounded_generation_service.CheckGroundingRequest, Sequence[Tuple[str, str]] + ]: + """Pre-rpc interceptor for check_grounding + + Override in a subclass to manipulate the request or metadata + before they are sent to the GroundedGenerationService server. + """ + return request, metadata + + def post_check_grounding( + self, response: grounded_generation_service.CheckGroundingResponse + ) -> grounded_generation_service.CheckGroundingResponse: + """Post-rpc interceptor for check_grounding + + Override in a subclass to manipulate the response + after it is returned by the GroundedGenerationService 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 GroundedGenerationService 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 GroundedGenerationService 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 GroundedGenerationService 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 GroundedGenerationService server but before + it is returned to user code. + """ + return response + + +@dataclasses.dataclass +class GroundedGenerationServiceRestStub: + _session: AuthorizedSession + _host: str + _interceptor: GroundedGenerationServiceRestInterceptor + + +class GroundedGenerationServiceRestTransport(GroundedGenerationServiceTransport): + """REST backend transport for GroundedGenerationService. + + Service for grounded generation. + + 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 = "discoveryengine.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[GroundedGenerationServiceRestInterceptor] = None, + api_audience: Optional[str] = None, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to (default: 'discoveryengine.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 GroundedGenerationServiceRestInterceptor() + self._prep_wrapped_messages(client_info) + + class _CheckGrounding(GroundedGenerationServiceRestStub): + def __hash__(self): + return hash("CheckGrounding") + + __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: grounded_generation_service.CheckGroundingRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> grounded_generation_service.CheckGroundingResponse: + r"""Call the check grounding method over HTTP. + + Args: + request (~.grounded_generation_service.CheckGroundingRequest): + The request object. Request message for + [GroundedGenerationService.CheckGrounding][google.cloud.discoveryengine.v1alpha.GroundedGenerationService.CheckGrounding] + 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: + ~.grounded_generation_service.CheckGroundingResponse: + Response message for the + [GroundedGenerationService.CheckGrounding][google.cloud.discoveryengine.v1alpha.GroundedGenerationService.CheckGrounding] + method. + + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "post", + "uri": "/v1alpha/{grounding_config=projects/*/locations/*/groundingConfigs/*}:check", + "body": "*", + }, + ] + request, metadata = self._interceptor.pre_check_grounding(request, metadata) + pb_request = grounded_generation_service.CheckGroundingRequest.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 = grounded_generation_service.CheckGroundingResponse() + pb_resp = grounded_generation_service.CheckGroundingResponse.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + resp = self._interceptor.post_check_grounding(resp) + return resp + + @property + def check_grounding( + self, + ) -> Callable[ + [grounded_generation_service.CheckGroundingRequest], + grounded_generation_service.CheckGroundingResponse, + ]: + # 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._CheckGrounding(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(GroundedGenerationServiceRestStub): + 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": "/v1alpha/{name=projects/*/locations/*/collections/*/dataConnector/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*/branches/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*/models/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*/schemas/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*/siteSearchEngine/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*/siteSearchEngine/targetSites/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/engines/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*/branches/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*/models/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/evaluations/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{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(GroundedGenerationServiceRestStub): + 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": "/v1alpha/{name=projects/*/locations/*/collections/*/dataConnector}/operations", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*/branches/*}/operations", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*/models/*}/operations", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*/schemas/*}/operations", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*/siteSearchEngine/targetSites}/operations", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*/siteSearchEngine}/operations", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*}/operations", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/engines/*}/operations", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*}/operations", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*/branches/*}/operations", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*/models/*}/operations", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*}/operations", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*}/operations", + }, + { + "method": "get", + "uri": "/v1alpha/{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__ = ("GroundedGenerationServiceRestTransport",) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/project_service/__init__.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/project_service/__init__.py new file mode 100644 index 000000000000..245aea0dfd81 --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/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-discoveryengine/google/cloud/discoveryengine_v1alpha/services/project_service/async_client.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/project_service/async_client.py new file mode 100644 index 000000000000..497cc0f19369 --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/project_service/async_client.py @@ -0,0 +1,790 @@ +# -*- 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 functools +import re +from typing import ( + 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.discoveryengine_v1alpha 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.api_core import operation # type: ignore +from google.api_core import operation_async # type: ignore +from google.cloud.location import locations_pb2 # type: ignore +from google.longrunning import operations_pb2 # type: ignore +from google.protobuf import timestamp_pb2 # type: ignore + +from google.cloud.discoveryengine_v1alpha.types import project +from google.cloud.discoveryengine_v1alpha.types import project as gcd_project +from google.cloud.discoveryengine_v1alpha.types import project_service + +from .client import ProjectServiceClient +from .transports.base import DEFAULT_CLIENT_INFO, ProjectServiceTransport +from .transports.grpc_asyncio import ProjectServiceGrpcAsyncIOTransport + + +class ProjectServiceAsyncClient: + """Service for operations on the + [Project][google.cloud.discoveryengine.v1alpha.Project]. + """ + + _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 + + project_path = staticmethod(ProjectServiceClient.project_path) + parse_project_path = staticmethod(ProjectServiceClient.parse_project_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 = functools.partial( + type(ProjectServiceClient).get_transport_class, type(ProjectServiceClient) + ) + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Union[str, 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 (Union[str, ~.ProjectServiceTransport]): The + transport to use. 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_project( + self, + request: Optional[Union[project_service.GetProjectRequest, 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.Project: + r"""Gets a [Project][google.cloud.discoveryengine.v1alpha.Project]. + Returns NOT_FOUND when the project is not yet created. + + .. 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 discoveryengine_v1alpha + + async def sample_get_project(): + # Create a client + client = discoveryengine_v1alpha.ProjectServiceAsyncClient() + + # Initialize request argument(s) + request = discoveryengine_v1alpha.GetProjectRequest( + name="name_value", + ) + + # Make the request + response = await client.get_project(request=request) + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.discoveryengine_v1alpha.types.GetProjectRequest, dict]]): + The request object. Request message for + [ProjectService.GetProject][google.cloud.discoveryengine.v1alpha.ProjectService.GetProject] + method. + name (:class:`str`): + Required. Full resource name of a + [Project][google.cloud.discoveryengine.v1alpha.Project], + such as ``projects/{project_id_or_number}``. + + 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.discoveryengine_v1alpha.types.Project: + Metadata and configurations for a + Google Cloud project in the service. + + """ + # 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." + ) + + request = project_service.GetProjectRequest(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 = gapic_v1.method_async.wrap_method( + self._client._transport.get_project, + 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 provision_project( + self, + request: Optional[Union[project_service.ProvisionProjectRequest, 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]] = (), + ) -> operation_async.AsyncOperation: + r"""Provisions the project resource. During the process, related + systems will get prepared and initialized. + + Caller must read the `Terms for data + use `__, and + optionally specify in request to provide consent to that service + terms. + + .. 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 discoveryengine_v1alpha + + async def sample_provision_project(): + # Create a client + client = discoveryengine_v1alpha.ProjectServiceAsyncClient() + + # Initialize request argument(s) + request = discoveryengine_v1alpha.ProvisionProjectRequest( + name="name_value", + accept_data_use_terms=True, + data_use_terms_version="data_use_terms_version_value", + ) + + # Make the request + operation = client.provision_project(request=request) + + print("Waiting for operation to complete...") + + response = (await operation).result() + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.discoveryengine_v1alpha.types.ProvisionProjectRequest, dict]]): + The request object. Request for + [ProjectService.ProvisionProject][google.cloud.discoveryengine.v1alpha.ProjectService.ProvisionProject] + method. + name (:class:`str`): + Required. Full resource name of a + [Project][google.cloud.discoveryengine.v1alpha.Project], + such as ``projects/{project_id_or_number}``. + + 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.api_core.operation_async.AsyncOperation: + An object representing a long-running operation. + + The result type for the operation will be + :class:`google.cloud.discoveryengine_v1alpha.types.Project` + Metadata and configurations for a Google Cloud project + in the service. + + """ + # 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." + ) + + request = project_service.ProvisionProjectRequest(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 = gapic_v1.method_async.wrap_method( + self._client._transport.provision_project, + 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, + ) + + # Wrap the response in an operation future. + response = operation_async.from_gapic( + response, + self._client._transport.operations_client, + project.Project, + metadata_type=project_service.ProvisionProjectMetadata, + ) + + # Done; return the response. + return response + + async def report_consent_change( + self, + request: Optional[ + Union[project_service.ReportConsentChangeRequest, dict] + ] = None, + *, + consent_change_action: Optional[ + project_service.ReportConsentChangeRequest.ConsentChangeAction + ] = None, + project: Optional[str] = None, + service_term_id: Optional[str] = None, + service_term_version: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> gcd_project.Project: + r"""Updates service terms for this project. + + This method can be used to retroactively accept the latest + terms. + + Terms available for update: + + - `Terms for data + use `__ + + .. 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 discoveryengine_v1alpha + + async def sample_report_consent_change(): + # Create a client + client = discoveryengine_v1alpha.ProjectServiceAsyncClient() + + # Initialize request argument(s) + request = discoveryengine_v1alpha.ReportConsentChangeRequest( + consent_change_action="ACCEPT", + project="project_value", + service_term_id="service_term_id_value", + service_term_version="service_term_version_value", + ) + + # Make the request + response = await client.report_consent_change(request=request) + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.discoveryengine_v1alpha.types.ReportConsentChangeRequest, dict]]): + The request object. Request for ReportConsentChange + method. + consent_change_action (:class:`google.cloud.discoveryengine_v1alpha.types.ReportConsentChangeRequest.ConsentChangeAction`): + Required. Whether customer decides to + accept or decline service term. + At this moment, only accept action is + supported. + + This corresponds to the ``consent_change_action`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + project (:class:`str`): + Required. Full resource name of a + [Project][google.cloud.discoveryengine.v1alpha.Project], + such as ``projects/{project_id_or_number}``. + + This corresponds to the ``project`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + service_term_id (:class:`str`): + Required. The unique identifier of the terms of service + to update. Available term ids: + + - ``GA_DATA_USE_TERMS``: `Terms for data + use `__. + When using this service term id, the acceptable + [service_term_version][google.cloud.discoveryengine.v1alpha.ReportConsentChangeRequest.service_term_version] + to provide is ``2022-11-23``. + + This corresponds to the ``service_term_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + service_term_version (:class:`str`): + Required. The version string of the + terms of service to update. + + This corresponds to the ``service_term_version`` 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.discoveryengine_v1alpha.types.Project: + Metadata and configurations for a + Google Cloud project in the service. + + """ + # 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( + [consent_change_action, project, service_term_id, service_term_version] + ) + 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." + ) + + request = project_service.ReportConsentChangeRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if consent_change_action is not None: + request.consent_change_action = consent_change_action + if project is not None: + request.project = project + if service_term_id is not None: + request.service_term_id = service_term_id + if service_term_version is not None: + request.service_term_version = service_term_version + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method_async.wrap_method( + self._client._transport.report_consent_change, + 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((("project", request.project),)), + ) + + # 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-discoveryengine/google/cloud/discoveryengine_v1alpha/services/project_service/client.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/project_service/client.py new file mode 100644 index 000000000000..5dca3913632e --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/project_service/client.py @@ -0,0 +1,1203 @@ +# -*- 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 ( + 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.discoveryengine_v1alpha 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.api_core import operation # type: ignore +from google.api_core import operation_async # type: ignore +from google.cloud.location import locations_pb2 # type: ignore +from google.longrunning import operations_pb2 # type: ignore +from google.protobuf import timestamp_pb2 # type: ignore + +from google.cloud.discoveryengine_v1alpha.types import project +from google.cloud.discoveryengine_v1alpha.types import project as gcd_project +from google.cloud.discoveryengine_v1alpha.types import 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 operations on the + [Project][google.cloud.discoveryengine.v1alpha.Project]. + """ + + @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 = "discoveryengine.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "discoveryengine.{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 project_path( + project: str, + ) -> str: + """Returns a fully-qualified project string.""" + return "projects/{project}".format( + project=project, + ) + + @staticmethod + def parse_project_path(path: str) -> Dict[str, str]: + """Parses a project path into its component segments.""" + m = re.match(r"^projects/(?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 = 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]] = 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 (Union[str, ProjectServiceTransport]): The + transport to use. 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 = type(self).get_transport_class(cast(str, transport)) + self._transport = Transport( + 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_project( + self, + request: Optional[Union[project_service.GetProjectRequest, 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.Project: + r"""Gets a [Project][google.cloud.discoveryengine.v1alpha.Project]. + Returns NOT_FOUND when the project is not yet created. + + .. 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 discoveryengine_v1alpha + + def sample_get_project(): + # Create a client + client = discoveryengine_v1alpha.ProjectServiceClient() + + # Initialize request argument(s) + request = discoveryengine_v1alpha.GetProjectRequest( + name="name_value", + ) + + # Make the request + response = client.get_project(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.discoveryengine_v1alpha.types.GetProjectRequest, dict]): + The request object. Request message for + [ProjectService.GetProject][google.cloud.discoveryengine.v1alpha.ProjectService.GetProject] + method. + name (str): + Required. Full resource name of a + [Project][google.cloud.discoveryengine.v1alpha.Project], + such as ``projects/{project_id_or_number}``. + + 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.discoveryengine_v1alpha.types.Project: + Metadata and configurations for a + Google Cloud project in the service. + + """ + # 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." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a project_service.GetProjectRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance(request, project_service.GetProjectRequest): + request = project_service.GetProjectRequest(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_project] + + # 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 provision_project( + self, + request: Optional[Union[project_service.ProvisionProjectRequest, 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]] = (), + ) -> operation.Operation: + r"""Provisions the project resource. During the process, related + systems will get prepared and initialized. + + Caller must read the `Terms for data + use `__, and + optionally specify in request to provide consent to that service + terms. + + .. 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 discoveryengine_v1alpha + + def sample_provision_project(): + # Create a client + client = discoveryengine_v1alpha.ProjectServiceClient() + + # Initialize request argument(s) + request = discoveryengine_v1alpha.ProvisionProjectRequest( + name="name_value", + accept_data_use_terms=True, + data_use_terms_version="data_use_terms_version_value", + ) + + # Make the request + operation = client.provision_project(request=request) + + print("Waiting for operation to complete...") + + response = operation.result() + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.discoveryengine_v1alpha.types.ProvisionProjectRequest, dict]): + The request object. Request for + [ProjectService.ProvisionProject][google.cloud.discoveryengine.v1alpha.ProjectService.ProvisionProject] + method. + name (str): + Required. Full resource name of a + [Project][google.cloud.discoveryengine.v1alpha.Project], + such as ``projects/{project_id_or_number}``. + + 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.api_core.operation.Operation: + An object representing a long-running operation. + + The result type for the operation will be + :class:`google.cloud.discoveryengine_v1alpha.types.Project` + Metadata and configurations for a Google Cloud project + in the service. + + """ + # 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." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a project_service.ProvisionProjectRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance(request, project_service.ProvisionProjectRequest): + request = project_service.ProvisionProjectRequest(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.provision_project] + + # 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, + ) + + # Wrap the response in an operation future. + response = operation.from_gapic( + response, + self._transport.operations_client, + project.Project, + metadata_type=project_service.ProvisionProjectMetadata, + ) + + # Done; return the response. + return response + + def report_consent_change( + self, + request: Optional[ + Union[project_service.ReportConsentChangeRequest, dict] + ] = None, + *, + consent_change_action: Optional[ + project_service.ReportConsentChangeRequest.ConsentChangeAction + ] = None, + project: Optional[str] = None, + service_term_id: Optional[str] = None, + service_term_version: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> gcd_project.Project: + r"""Updates service terms for this project. + + This method can be used to retroactively accept the latest + terms. + + Terms available for update: + + - `Terms for data + use `__ + + .. 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 discoveryengine_v1alpha + + def sample_report_consent_change(): + # Create a client + client = discoveryengine_v1alpha.ProjectServiceClient() + + # Initialize request argument(s) + request = discoveryengine_v1alpha.ReportConsentChangeRequest( + consent_change_action="ACCEPT", + project="project_value", + service_term_id="service_term_id_value", + service_term_version="service_term_version_value", + ) + + # Make the request + response = client.report_consent_change(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.discoveryengine_v1alpha.types.ReportConsentChangeRequest, dict]): + The request object. Request for ReportConsentChange + method. + consent_change_action (google.cloud.discoveryengine_v1alpha.types.ReportConsentChangeRequest.ConsentChangeAction): + Required. Whether customer decides to + accept or decline service term. + At this moment, only accept action is + supported. + + This corresponds to the ``consent_change_action`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + project (str): + Required. Full resource name of a + [Project][google.cloud.discoveryengine.v1alpha.Project], + such as ``projects/{project_id_or_number}``. + + This corresponds to the ``project`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + service_term_id (str): + Required. The unique identifier of the terms of service + to update. Available term ids: + + - ``GA_DATA_USE_TERMS``: `Terms for data + use `__. + When using this service term id, the acceptable + [service_term_version][google.cloud.discoveryengine.v1alpha.ReportConsentChangeRequest.service_term_version] + to provide is ``2022-11-23``. + + This corresponds to the ``service_term_id`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + service_term_version (str): + Required. The version string of the + terms of service to update. + + This corresponds to the ``service_term_version`` 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.discoveryengine_v1alpha.types.Project: + Metadata and configurations for a + Google Cloud project in the service. + + """ + # 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( + [consent_change_action, project, service_term_id, service_term_version] + ) + 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." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a project_service.ReportConsentChangeRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance(request, project_service.ReportConsentChangeRequest): + request = project_service.ReportConsentChangeRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if consent_change_action is not None: + request.consent_change_action = consent_change_action + if project is not None: + request.project = project + if service_term_id is not None: + request.service_term_id = service_term_id + if service_term_version is not None: + request.service_term_version = service_term_version + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.report_consent_change] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("project", request.project),)), + ) + + # 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-discoveryengine/google/cloud/discoveryengine_v1alpha/services/project_service/transports/__init__.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/project_service/transports/__init__.py new file mode 100644 index 000000000000..bfc15c764467 --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/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-discoveryengine/google/cloud/discoveryengine_v1alpha/services/project_service/transports/base.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/project_service/transports/base.py new file mode 100644 index 000000000000..7549460a8afd --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/project_service/transports/base.py @@ -0,0 +1,217 @@ +# -*- 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, operations_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.discoveryengine_v1alpha import gapic_version as package_version +from google.cloud.discoveryengine_v1alpha.types import project +from google.cloud.discoveryengine_v1alpha.types import project as gcd_project +from google.cloud.discoveryengine_v1alpha.types import 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 = "discoveryengine.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: 'discoveryengine.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 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: + 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_project: gapic_v1.method.wrap_method( + self.get_project, + default_timeout=None, + client_info=client_info, + ), + self.provision_project: gapic_v1.method.wrap_method( + self.provision_project, + default_timeout=None, + client_info=client_info, + ), + self.report_consent_change: gapic_v1.method.wrap_method( + self.report_consent_change, + 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 operations_client(self): + """Return the client designed to process long-running operations.""" + raise NotImplementedError() + + @property + def get_project( + self, + ) -> Callable[ + [project_service.GetProjectRequest], + Union[project.Project, Awaitable[project.Project]], + ]: + raise NotImplementedError() + + @property + def provision_project( + self, + ) -> Callable[ + [project_service.ProvisionProjectRequest], + Union[operations_pb2.Operation, Awaitable[operations_pb2.Operation]], + ]: + raise NotImplementedError() + + @property + def report_consent_change( + self, + ) -> Callable[ + [project_service.ReportConsentChangeRequest], + Union[gcd_project.Project, Awaitable[gcd_project.Project]], + ]: + 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-discoveryengine/google/cloud/discoveryengine_v1alpha/services/project_service/transports/grpc.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/project_service/transports/grpc.py new file mode 100644 index 000000000000..2bb66143e720 --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/project_service/transports/grpc.py @@ -0,0 +1,388 @@ +# -*- 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, operations_v1 +import google.auth # type: ignore +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.cloud.location import locations_pb2 # type: ignore +from google.longrunning import operations_pb2 # type: ignore +import grpc # type: ignore + +from google.cloud.discoveryengine_v1alpha.types import project +from google.cloud.discoveryengine_v1alpha.types import project as gcd_project +from google.cloud.discoveryengine_v1alpha.types import project_service + +from .base import DEFAULT_CLIENT_INFO, ProjectServiceTransport + + +class ProjectServiceGrpcTransport(ProjectServiceTransport): + """gRPC backend transport for ProjectService. + + Service for operations on the + [Project][google.cloud.discoveryengine.v1alpha.Project]. + + 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 = "discoveryengine.googleapis.com", + credentials: Optional[ga_credentials.Credentials] = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + channel: Optional[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: 'discoveryengine.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 ``channel`` 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 ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): 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 ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + 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] = {} + self._operations_client: Optional[operations_v1.OperationsClient] = None + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn("client_cert_source is deprecated", DeprecationWarning) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + 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: + self._grpc_channel = type(self).create_channel( + 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 = "discoveryengine.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 operations_client(self) -> operations_v1.OperationsClient: + """Create the client designed to process long-running operations. + + This property caches on the instance; repeated calls return the same + client. + """ + # Quick check: Only create a new client if we do not already have one. + if self._operations_client is None: + self._operations_client = operations_v1.OperationsClient(self.grpc_channel) + + # Return the client from cache. + return self._operations_client + + @property + def get_project( + self, + ) -> Callable[[project_service.GetProjectRequest], project.Project]: + r"""Return a callable for the get project method over gRPC. + + Gets a [Project][google.cloud.discoveryengine.v1alpha.Project]. + Returns NOT_FOUND when the project is not yet created. + + Returns: + Callable[[~.GetProjectRequest], + ~.Project]: + 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_project" not in self._stubs: + self._stubs["get_project"] = self.grpc_channel.unary_unary( + "/google.cloud.discoveryengine.v1alpha.ProjectService/GetProject", + request_serializer=project_service.GetProjectRequest.serialize, + response_deserializer=project.Project.deserialize, + ) + return self._stubs["get_project"] + + @property + def provision_project( + self, + ) -> Callable[[project_service.ProvisionProjectRequest], operations_pb2.Operation]: + r"""Return a callable for the provision project method over gRPC. + + Provisions the project resource. During the process, related + systems will get prepared and initialized. + + Caller must read the `Terms for data + use `__, and + optionally specify in request to provide consent to that service + terms. + + Returns: + Callable[[~.ProvisionProjectRequest], + ~.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 "provision_project" not in self._stubs: + self._stubs["provision_project"] = self.grpc_channel.unary_unary( + "/google.cloud.discoveryengine.v1alpha.ProjectService/ProvisionProject", + request_serializer=project_service.ProvisionProjectRequest.serialize, + response_deserializer=operations_pb2.Operation.FromString, + ) + return self._stubs["provision_project"] + + @property + def report_consent_change( + self, + ) -> Callable[[project_service.ReportConsentChangeRequest], gcd_project.Project]: + r"""Return a callable for the report consent change method over gRPC. + + Updates service terms for this project. + + This method can be used to retroactively accept the latest + terms. + + Terms available for update: + + - `Terms for data + use `__ + + Returns: + Callable[[~.ReportConsentChangeRequest], + ~.Project]: + 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 "report_consent_change" not in self._stubs: + self._stubs["report_consent_change"] = self.grpc_channel.unary_unary( + "/google.cloud.discoveryengine.v1alpha.ProjectService/ReportConsentChange", + request_serializer=project_service.ReportConsentChangeRequest.serialize, + response_deserializer=gcd_project.Project.deserialize, + ) + return self._stubs["report_consent_change"] + + 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-discoveryengine/google/cloud/discoveryengine_v1alpha/services/project_service/transports/grpc_asyncio.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/project_service/transports/grpc_asyncio.py new file mode 100644 index 000000000000..5dea5232e593 --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/project_service/transports/grpc_asyncio.py @@ -0,0 +1,393 @@ +# -*- 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 gapic_v1, grpc_helpers_async, operations_v1 +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.discoveryengine_v1alpha.types import project +from google.cloud.discoveryengine_v1alpha.types import project as gcd_project +from google.cloud.discoveryengine_v1alpha.types import project_service + +from .base import DEFAULT_CLIENT_INFO, ProjectServiceTransport +from .grpc import ProjectServiceGrpcTransport + + +class ProjectServiceGrpcAsyncIOTransport(ProjectServiceTransport): + """gRPC AsyncIO backend transport for ProjectService. + + Service for operations on the + [Project][google.cloud.discoveryengine.v1alpha.Project]. + + 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 = "discoveryengine.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`. + This argument is ignored if ``channel`` 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`. + 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 = "discoveryengine.googleapis.com", + credentials: Optional[ga_credentials.Credentials] = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + channel: Optional[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: 'discoveryengine.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 ``channel`` 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 ``channel`` 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[aio.Channel]): A ``Channel`` instance through + which to make calls. + 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 ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + 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] = {} + self._operations_client: Optional[operations_v1.OperationsAsyncClient] = None + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn("client_cert_source is deprecated", DeprecationWarning) + + if channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + 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: + self._grpc_channel = type(self).create_channel( + 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 operations_client(self) -> operations_v1.OperationsAsyncClient: + """Create the client designed to process long-running operations. + + This property caches on the instance; repeated calls return the same + client. + """ + # Quick check: Only create a new client if we do not already have one. + if self._operations_client is None: + self._operations_client = operations_v1.OperationsAsyncClient( + self.grpc_channel + ) + + # Return the client from cache. + return self._operations_client + + @property + def get_project( + self, + ) -> Callable[[project_service.GetProjectRequest], Awaitable[project.Project]]: + r"""Return a callable for the get project method over gRPC. + + Gets a [Project][google.cloud.discoveryengine.v1alpha.Project]. + Returns NOT_FOUND when the project is not yet created. + + Returns: + Callable[[~.GetProjectRequest], + Awaitable[~.Project]]: + 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_project" not in self._stubs: + self._stubs["get_project"] = self.grpc_channel.unary_unary( + "/google.cloud.discoveryengine.v1alpha.ProjectService/GetProject", + request_serializer=project_service.GetProjectRequest.serialize, + response_deserializer=project.Project.deserialize, + ) + return self._stubs["get_project"] + + @property + def provision_project( + self, + ) -> Callable[ + [project_service.ProvisionProjectRequest], Awaitable[operations_pb2.Operation] + ]: + r"""Return a callable for the provision project method over gRPC. + + Provisions the project resource. During the process, related + systems will get prepared and initialized. + + Caller must read the `Terms for data + use `__, and + optionally specify in request to provide consent to that service + terms. + + Returns: + Callable[[~.ProvisionProjectRequest], + 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 "provision_project" not in self._stubs: + self._stubs["provision_project"] = self.grpc_channel.unary_unary( + "/google.cloud.discoveryengine.v1alpha.ProjectService/ProvisionProject", + request_serializer=project_service.ProvisionProjectRequest.serialize, + response_deserializer=operations_pb2.Operation.FromString, + ) + return self._stubs["provision_project"] + + @property + def report_consent_change( + self, + ) -> Callable[ + [project_service.ReportConsentChangeRequest], Awaitable[gcd_project.Project] + ]: + r"""Return a callable for the report consent change method over gRPC. + + Updates service terms for this project. + + This method can be used to retroactively accept the latest + terms. + + Terms available for update: + + - `Terms for data + use `__ + + Returns: + Callable[[~.ReportConsentChangeRequest], + Awaitable[~.Project]]: + 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 "report_consent_change" not in self._stubs: + self._stubs["report_consent_change"] = self.grpc_channel.unary_unary( + "/google.cloud.discoveryengine.v1alpha.ProjectService/ReportConsentChange", + request_serializer=project_service.ReportConsentChangeRequest.serialize, + response_deserializer=gcd_project.Project.deserialize, + ) + return self._stubs["report_consent_change"] + + 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-discoveryengine/google/cloud/discoveryengine_v1alpha/services/project_service/transports/rest.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/project_service/transports/rest.py new file mode 100644 index 000000000000..4fb549898e20 --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/project_service/transports/rest.py @@ -0,0 +1,1022 @@ +# -*- 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, + operations_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.discoveryengine_v1alpha.types import project +from google.cloud.discoveryengine_v1alpha.types import project as gcd_project +from google.cloud.discoveryengine_v1alpha.types import 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_project(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_get_project(self, response): + logging.log(f"Received response: {response}") + return response + + def pre_provision_project(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_provision_project(self, response): + logging.log(f"Received response: {response}") + return response + + def pre_report_consent_change(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_report_consent_change(self, response): + logging.log(f"Received response: {response}") + return response + + transport = ProjectServiceRestTransport(interceptor=MyCustomProjectServiceInterceptor()) + client = ProjectServiceClient(transport=transport) + + + """ + + def pre_get_project( + self, + request: project_service.GetProjectRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[project_service.GetProjectRequest, Sequence[Tuple[str, str]]]: + """Pre-rpc interceptor for get_project + + Override in a subclass to manipulate the request or metadata + before they are sent to the ProjectService server. + """ + return request, metadata + + def post_get_project(self, response: project.Project) -> project.Project: + """Post-rpc interceptor for get_project + + 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_provision_project( + self, + request: project_service.ProvisionProjectRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[project_service.ProvisionProjectRequest, Sequence[Tuple[str, str]]]: + """Pre-rpc interceptor for provision_project + + Override in a subclass to manipulate the request or metadata + before they are sent to the ProjectService server. + """ + return request, metadata + + def post_provision_project( + self, response: operations_pb2.Operation + ) -> operations_pb2.Operation: + """Post-rpc interceptor for provision_project + + 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_report_consent_change( + self, + request: project_service.ReportConsentChangeRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[project_service.ReportConsentChangeRequest, Sequence[Tuple[str, str]]]: + """Pre-rpc interceptor for report_consent_change + + Override in a subclass to manipulate the request or metadata + before they are sent to the ProjectService server. + """ + return request, metadata + + def post_report_consent_change( + self, response: gcd_project.Project + ) -> gcd_project.Project: + """Post-rpc interceptor for report_consent_change + + 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 operations on the + [Project][google.cloud.discoveryengine.v1alpha.Project]. + + 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 = "discoveryengine.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: 'discoveryengine.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 + ) + self._operations_client: Optional[operations_v1.AbstractOperationsClient] = None + 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) + + @property + def operations_client(self) -> operations_v1.AbstractOperationsClient: + """Create the client designed to process long-running operations. + + This property caches on the instance; repeated calls return the same + client. + """ + # Only create a new client if we do not already have one. + if self._operations_client is None: + http_options: Dict[str, List[Dict[str, str]]] = { + "google.longrunning.Operations.GetOperation": [ + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataConnector/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*/branches/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*/models/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*/schemas/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*/siteSearchEngine/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*/siteSearchEngine/targetSites/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/engines/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*/branches/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*/models/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/evaluations/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/operations/*}", + }, + ], + "google.longrunning.Operations.ListOperations": [ + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataConnector}/operations", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*/branches/*}/operations", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*/models/*}/operations", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*/schemas/*}/operations", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*/siteSearchEngine/targetSites}/operations", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*/siteSearchEngine}/operations", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*}/operations", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/engines/*}/operations", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*}/operations", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*/branches/*}/operations", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*/models/*}/operations", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*}/operations", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*}/operations", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*}/operations", + }, + ], + } + + rest_transport = operations_v1.OperationsRestTransport( + host=self._host, + # use the credentials which are saved + credentials=self._credentials, + scopes=self._scopes, + http_options=http_options, + path_prefix="v1alpha", + ) + + self._operations_client = operations_v1.AbstractOperationsClient( + transport=rest_transport + ) + + # Return the client from cache. + return self._operations_client + + class _GetProject(ProjectServiceRestStub): + def __hash__(self): + return hash("GetProject") + + __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.GetProjectRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> project.Project: + r"""Call the get project method over HTTP. + + Args: + request (~.project_service.GetProjectRequest): + The request object. Request message for + [ProjectService.GetProject][google.cloud.discoveryengine.v1alpha.ProjectService.GetProject] + 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.Project: + Metadata and configurations for a + Google Cloud project in the service. + + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "get", + "uri": "/v1alpha/{name=projects/*}", + }, + ] + request, metadata = self._interceptor.pre_get_project(request, metadata) + pb_request = project_service.GetProjectRequest.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.Project() + pb_resp = project.Project.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + resp = self._interceptor.post_get_project(resp) + return resp + + class _ProvisionProject(ProjectServiceRestStub): + def __hash__(self): + return hash("ProvisionProject") + + __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.ProvisionProjectRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operations_pb2.Operation: + r"""Call the provision project method over HTTP. + + Args: + request (~.project_service.ProvisionProjectRequest): + The request object. Request for + [ProjectService.ProvisionProject][google.cloud.discoveryengine.v1alpha.ProjectService.ProvisionProject] + 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": "/v1alpha/{name=projects/*}:provision", + "body": "*", + }, + ] + request, metadata = self._interceptor.pre_provision_project( + request, metadata + ) + pb_request = project_service.ProvisionProjectRequest.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_provision_project(resp) + return resp + + class _ReportConsentChange(ProjectServiceRestStub): + def __hash__(self): + return hash("ReportConsentChange") + + __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.ReportConsentChangeRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> gcd_project.Project: + r"""Call the report consent change method over HTTP. + + Args: + request (~.project_service.ReportConsentChangeRequest): + The request object. Request for ReportConsentChange + 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: + ~.gcd_project.Project: + Metadata and configurations for a + Google Cloud project in the service. + + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "post", + "uri": "/v1alpha/{project=projects/*}:reportConsentChange", + "body": "*", + }, + ] + request, metadata = self._interceptor.pre_report_consent_change( + request, metadata + ) + pb_request = project_service.ReportConsentChangeRequest.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 = gcd_project.Project() + pb_resp = gcd_project.Project.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + resp = self._interceptor.post_report_consent_change(resp) + return resp + + @property + def get_project( + self, + ) -> Callable[[project_service.GetProjectRequest], project.Project]: + # 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._GetProject(self._session, self._host, self._interceptor) # type: ignore + + @property + def provision_project( + self, + ) -> Callable[[project_service.ProvisionProjectRequest], 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._ProvisionProject(self._session, self._host, self._interceptor) # type: ignore + + @property + def report_consent_change( + self, + ) -> Callable[[project_service.ReportConsentChangeRequest], gcd_project.Project]: + # 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._ReportConsentChange(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": "/v1alpha/{name=projects/*/locations/*/collections/*/dataConnector/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*/branches/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*/models/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*/schemas/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*/siteSearchEngine/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*/siteSearchEngine/targetSites/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/engines/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*/branches/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*/models/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/evaluations/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{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": "/v1alpha/{name=projects/*/locations/*/collections/*/dataConnector}/operations", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*/branches/*}/operations", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*/models/*}/operations", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*/schemas/*}/operations", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*/siteSearchEngine/targetSites}/operations", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*/siteSearchEngine}/operations", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*}/operations", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/engines/*}/operations", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*}/operations", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*/branches/*}/operations", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*/models/*}/operations", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*}/operations", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*}/operations", + }, + { + "method": "get", + "uri": "/v1alpha/{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-discoveryengine/google/cloud/discoveryengine_v1alpha/services/rank_service/__init__.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/rank_service/__init__.py new file mode 100644 index 000000000000..f34036ed49c9 --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/rank_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 RankServiceAsyncClient +from .client import RankServiceClient + +__all__ = ( + "RankServiceClient", + "RankServiceAsyncClient", +) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/rank_service/async_client.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/rank_service/async_client.py new file mode 100644 index 000000000000..255c96741a2f --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/rank_service/async_client.py @@ -0,0 +1,469 @@ +# -*- 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 functools +import re +from typing import ( + 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.discoveryengine_v1alpha 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.cloud.discoveryengine_v1alpha.types import rank_service + +from .client import RankServiceClient +from .transports.base import DEFAULT_CLIENT_INFO, RankServiceTransport +from .transports.grpc_asyncio import RankServiceGrpcAsyncIOTransport + + +class RankServiceAsyncClient: + """Service for ranking text records.""" + + _client: RankServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = RankServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = RankServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = RankServiceClient._DEFAULT_ENDPOINT_TEMPLATE + _DEFAULT_UNIVERSE = RankServiceClient._DEFAULT_UNIVERSE + + ranking_config_path = staticmethod(RankServiceClient.ranking_config_path) + parse_ranking_config_path = staticmethod( + RankServiceClient.parse_ranking_config_path + ) + common_billing_account_path = staticmethod( + RankServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + RankServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod(RankServiceClient.common_folder_path) + parse_common_folder_path = staticmethod(RankServiceClient.parse_common_folder_path) + common_organization_path = staticmethod(RankServiceClient.common_organization_path) + parse_common_organization_path = staticmethod( + RankServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod(RankServiceClient.common_project_path) + parse_common_project_path = staticmethod( + RankServiceClient.parse_common_project_path + ) + common_location_path = staticmethod(RankServiceClient.common_location_path) + parse_common_location_path = staticmethod( + RankServiceClient.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: + RankServiceAsyncClient: The constructed client. + """ + return RankServiceClient.from_service_account_info.__func__(RankServiceAsyncClient, 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: + RankServiceAsyncClient: The constructed client. + """ + return RankServiceClient.from_service_account_file.__func__(RankServiceAsyncClient, 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 RankServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> RankServiceTransport: + """Returns the transport used by the client instance. + + Returns: + RankServiceTransport: 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 = functools.partial( + type(RankServiceClient).get_transport_class, type(RankServiceClient) + ) + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Union[str, RankServiceTransport] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the rank 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 (Union[str, ~.RankServiceTransport]): The + transport to use. 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 = RankServiceClient( + credentials=credentials, + transport=transport, + client_options=client_options, + client_info=client_info, + ) + + async def rank( + self, + request: Optional[Union[rank_service.RankRequest, dict]] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> rank_service.RankResponse: + r"""Ranks a list of text records based on the given input + query. + + .. 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 discoveryengine_v1alpha + + async def sample_rank(): + # Create a client + client = discoveryengine_v1alpha.RankServiceAsyncClient() + + # Initialize request argument(s) + request = discoveryengine_v1alpha.RankRequest( + ranking_config="ranking_config_value", + ) + + # Make the request + response = await client.rank(request=request) + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.discoveryengine_v1alpha.types.RankRequest, dict]]): + The request object. Request message for + [RankService.Rank][google.cloud.discoveryengine.v1alpha.RankService.Rank] + 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.cloud.discoveryengine_v1alpha.types.RankResponse: + Response message for + [RankService.Rank][google.cloud.discoveryengine.v1alpha.RankService.Rank] + method. + + """ + # Create or coerce a protobuf request object. + request = rank_service.RankRequest(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.rank, + 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( + (("ranking_config", request.ranking_config),) + ), + ) + + # 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) -> "RankServiceAsyncClient": + 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__ = ("RankServiceAsyncClient",) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/rank_service/client.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/rank_service/client.py new file mode 100644 index 000000000000..1d5ad3325014 --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/rank_service/client.py @@ -0,0 +1,887 @@ +# -*- 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 ( + 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.discoveryengine_v1alpha 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.cloud.discoveryengine_v1alpha.types import rank_service + +from .transports.base import DEFAULT_CLIENT_INFO, RankServiceTransport +from .transports.grpc import RankServiceGrpcTransport +from .transports.grpc_asyncio import RankServiceGrpcAsyncIOTransport +from .transports.rest import RankServiceRestTransport + + +class RankServiceClientMeta(type): + """Metaclass for the RankService 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[RankServiceTransport]] + _transport_registry["grpc"] = RankServiceGrpcTransport + _transport_registry["grpc_asyncio"] = RankServiceGrpcAsyncIOTransport + _transport_registry["rest"] = RankServiceRestTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[RankServiceTransport]: + """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 RankServiceClient(metaclass=RankServiceClientMeta): + """Service for ranking text records.""" + + @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 = "discoveryengine.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "discoveryengine.{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: + RankServiceClient: 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: + RankServiceClient: 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) -> RankServiceTransport: + """Returns the transport used by the client instance. + + Returns: + RankServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def ranking_config_path( + project: str, + location: str, + ranking_config: str, + ) -> str: + """Returns a fully-qualified ranking_config string.""" + return "projects/{project}/locations/{location}/rankingConfigs/{ranking_config}".format( + project=project, + location=location, + ranking_config=ranking_config, + ) + + @staticmethod + def parse_ranking_config_path(path: str) -> Dict[str, str]: + """Parses a ranking_config path into its component segments.""" + m = re.match( + r"^projects/(?P.+?)/locations/(?P.+?)/rankingConfigs/(?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 = RankServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = RankServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = RankServiceClient._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 = RankServiceClient._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 = RankServiceClient._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 RankServiceClient._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, RankServiceTransport]] = None, + client_options: Optional[Union[client_options_lib.ClientOptions, dict]] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the rank 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 (Union[str, RankServiceTransport]): The + transport to use. 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, + ) = RankServiceClient._read_environment_variables() + self._client_cert_source = RankServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + self._universe_domain = RankServiceClient._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, RankServiceTransport) + if transport_provided: + # transport is a RankServiceTransport 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(RankServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = self._api_endpoint or RankServiceClient._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 = type(self).get_transport_class(cast(str, transport)) + self._transport = Transport( + 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 rank( + self, + request: Optional[Union[rank_service.RankRequest, dict]] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> rank_service.RankResponse: + r"""Ranks a list of text records based on the given input + query. + + .. 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 discoveryengine_v1alpha + + def sample_rank(): + # Create a client + client = discoveryengine_v1alpha.RankServiceClient() + + # Initialize request argument(s) + request = discoveryengine_v1alpha.RankRequest( + ranking_config="ranking_config_value", + ) + + # Make the request + response = client.rank(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.discoveryengine_v1alpha.types.RankRequest, dict]): + The request object. Request message for + [RankService.Rank][google.cloud.discoveryengine.v1alpha.RankService.Rank] + 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.cloud.discoveryengine_v1alpha.types.RankResponse: + Response message for + [RankService.Rank][google.cloud.discoveryengine.v1alpha.RankService.Rank] + method. + + """ + # Create or coerce a protobuf request object. + # Minor optimization to avoid making a copy if the user passes + # in a rank_service.RankRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance(request, rank_service.RankRequest): + request = rank_service.RankRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.rank] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("ranking_config", request.ranking_config),) + ), + ) + + # 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) -> "RankServiceClient": + 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__ = ("RankServiceClient",) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/rank_service/transports/__init__.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/rank_service/transports/__init__.py new file mode 100644 index 000000000000..0084baa3bfcc --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/rank_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 RankServiceTransport +from .grpc import RankServiceGrpcTransport +from .grpc_asyncio import RankServiceGrpcAsyncIOTransport +from .rest import RankServiceRestInterceptor, RankServiceRestTransport + +# Compile a registry of transports. +_transport_registry = OrderedDict() # type: Dict[str, Type[RankServiceTransport]] +_transport_registry["grpc"] = RankServiceGrpcTransport +_transport_registry["grpc_asyncio"] = RankServiceGrpcAsyncIOTransport +_transport_registry["rest"] = RankServiceRestTransport + +__all__ = ( + "RankServiceTransport", + "RankServiceGrpcTransport", + "RankServiceGrpcAsyncIOTransport", + "RankServiceRestTransport", + "RankServiceRestInterceptor", +) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/rank_service/transports/base.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/rank_service/transports/base.py new file mode 100644 index 000000000000..66a0514579f2 --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/rank_service/transports/base.py @@ -0,0 +1,182 @@ +# -*- 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.discoveryengine_v1alpha import gapic_version as package_version +from google.cloud.discoveryengine_v1alpha.types import rank_service + +DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=package_version.__version__ +) + + +class RankServiceTransport(abc.ABC): + """Abstract transport class for RankService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/cloud-platform",) + + DEFAULT_HOST: str = "discoveryengine.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: 'discoveryengine.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 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: + 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.rank: gapic_v1.method.wrap_method( + self.rank, + 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 rank( + self, + ) -> Callable[ + [rank_service.RankRequest], + Union[rank_service.RankResponse, Awaitable[rank_service.RankResponse]], + ]: + 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__ = ("RankServiceTransport",) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/rank_service/transports/grpc.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/rank_service/transports/grpc.py new file mode 100644 index 000000000000..d5b8acd58595 --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/rank_service/transports/grpc.py @@ -0,0 +1,302 @@ +# -*- 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.discoveryengine_v1alpha.types import rank_service + +from .base import DEFAULT_CLIENT_INFO, RankServiceTransport + + +class RankServiceGrpcTransport(RankServiceTransport): + """gRPC backend transport for RankService. + + Service for ranking text records. + + 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 = "discoveryengine.googleapis.com", + credentials: Optional[ga_credentials.Credentials] = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + channel: Optional[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: 'discoveryengine.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 ``channel`` 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 ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): 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 ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + 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 channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + 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: + self._grpc_channel = type(self).create_channel( + 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 = "discoveryengine.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 rank(self) -> Callable[[rank_service.RankRequest], rank_service.RankResponse]: + r"""Return a callable for the rank method over gRPC. + + Ranks a list of text records based on the given input + query. + + Returns: + Callable[[~.RankRequest], + ~.RankResponse]: + 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 "rank" not in self._stubs: + self._stubs["rank"] = self.grpc_channel.unary_unary( + "/google.cloud.discoveryengine.v1alpha.RankService/Rank", + request_serializer=rank_service.RankRequest.serialize, + response_deserializer=rank_service.RankResponse.deserialize, + ) + return self._stubs["rank"] + + 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__ = ("RankServiceGrpcTransport",) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/rank_service/transports/grpc_asyncio.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/rank_service/transports/grpc_asyncio.py new file mode 100644 index 000000000000..40aed2d9dc58 --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/rank_service/transports/grpc_asyncio.py @@ -0,0 +1,303 @@ +# -*- 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 gapic_v1, grpc_helpers_async +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.discoveryengine_v1alpha.types import rank_service + +from .base import DEFAULT_CLIENT_INFO, RankServiceTransport +from .grpc import RankServiceGrpcTransport + + +class RankServiceGrpcAsyncIOTransport(RankServiceTransport): + """gRPC AsyncIO backend transport for RankService. + + Service for ranking text records. + + 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 = "discoveryengine.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`. + This argument is ignored if ``channel`` 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`. + 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 = "discoveryengine.googleapis.com", + credentials: Optional[ga_credentials.Credentials] = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + channel: Optional[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: 'discoveryengine.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 ``channel`` 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 ``channel`` 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[aio.Channel]): A ``Channel`` instance through + which to make calls. + 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 ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + 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 channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + 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: + self._grpc_channel = type(self).create_channel( + 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 rank( + self, + ) -> Callable[[rank_service.RankRequest], Awaitable[rank_service.RankResponse]]: + r"""Return a callable for the rank method over gRPC. + + Ranks a list of text records based on the given input + query. + + Returns: + Callable[[~.RankRequest], + Awaitable[~.RankResponse]]: + 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 "rank" not in self._stubs: + self._stubs["rank"] = self.grpc_channel.unary_unary( + "/google.cloud.discoveryengine.v1alpha.RankService/Rank", + request_serializer=rank_service.RankRequest.serialize, + response_deserializer=rank_service.RankResponse.deserialize, + ) + return self._stubs["rank"] + + 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__ = ("RankServiceGrpcAsyncIOTransport",) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/rank_service/transports/rest.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/rank_service/transports/rest.py new file mode 100644 index 000000000000..fb339d0730e0 --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/rank_service/transports/rest.py @@ -0,0 +1,598 @@ +# -*- 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.discoveryengine_v1alpha.types import rank_service + +from .base import DEFAULT_CLIENT_INFO as BASE_DEFAULT_CLIENT_INFO +from .base import RankServiceTransport + +DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=BASE_DEFAULT_CLIENT_INFO.gapic_version, + grpc_version=None, + rest_version=requests_version, +) + + +class RankServiceRestInterceptor: + """Interceptor for RankService. + + 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 RankServiceRestTransport. + + .. code-block:: python + class MyCustomRankServiceInterceptor(RankServiceRestInterceptor): + def pre_rank(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_rank(self, response): + logging.log(f"Received response: {response}") + return response + + transport = RankServiceRestTransport(interceptor=MyCustomRankServiceInterceptor()) + client = RankServiceClient(transport=transport) + + + """ + + def pre_rank( + self, request: rank_service.RankRequest, metadata: Sequence[Tuple[str, str]] + ) -> Tuple[rank_service.RankRequest, Sequence[Tuple[str, str]]]: + """Pre-rpc interceptor for rank + + Override in a subclass to manipulate the request or metadata + before they are sent to the RankService server. + """ + return request, metadata + + def post_rank( + self, response: rank_service.RankResponse + ) -> rank_service.RankResponse: + """Post-rpc interceptor for rank + + Override in a subclass to manipulate the response + after it is returned by the RankService 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 RankService 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 RankService 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 RankService 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 RankService server but before + it is returned to user code. + """ + return response + + +@dataclasses.dataclass +class RankServiceRestStub: + _session: AuthorizedSession + _host: str + _interceptor: RankServiceRestInterceptor + + +class RankServiceRestTransport(RankServiceTransport): + """REST backend transport for RankService. + + Service for ranking text records. + + 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 = "discoveryengine.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[RankServiceRestInterceptor] = None, + api_audience: Optional[str] = None, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to (default: 'discoveryengine.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 RankServiceRestInterceptor() + self._prep_wrapped_messages(client_info) + + class _Rank(RankServiceRestStub): + def __hash__(self): + return hash("Rank") + + __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: rank_service.RankRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> rank_service.RankResponse: + r"""Call the rank method over HTTP. + + Args: + request (~.rank_service.RankRequest): + The request object. Request message for + [RankService.Rank][google.cloud.discoveryengine.v1alpha.RankService.Rank] + 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: + ~.rank_service.RankResponse: + Response message for + [RankService.Rank][google.cloud.discoveryengine.v1alpha.RankService.Rank] + method. + + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "post", + "uri": "/v1alpha/{ranking_config=projects/*/locations/*/rankingConfigs/*}:rank", + "body": "*", + }, + ] + request, metadata = self._interceptor.pre_rank(request, metadata) + pb_request = rank_service.RankRequest.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 = rank_service.RankResponse() + pb_resp = rank_service.RankResponse.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + resp = self._interceptor.post_rank(resp) + return resp + + @property + def rank(self) -> Callable[[rank_service.RankRequest], rank_service.RankResponse]: + # 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._Rank(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(RankServiceRestStub): + 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": "/v1alpha/{name=projects/*/locations/*/collections/*/dataConnector/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*/branches/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*/models/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*/schemas/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*/siteSearchEngine/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*/siteSearchEngine/targetSites/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/engines/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*/branches/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*/models/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/evaluations/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1alpha/{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(RankServiceRestStub): + 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": "/v1alpha/{name=projects/*/locations/*/collections/*/dataConnector}/operations", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*/branches/*}/operations", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*/models/*}/operations", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*/schemas/*}/operations", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*/siteSearchEngine/targetSites}/operations", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*/siteSearchEngine}/operations", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/dataStores/*}/operations", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*/engines/*}/operations", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/collections/*}/operations", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*/branches/*}/operations", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*/models/*}/operations", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*}/operations", + }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*}/operations", + }, + { + "method": "get", + "uri": "/v1alpha/{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__ = ("RankServiceRestTransport",) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/recommendation_service/transports/rest.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/recommendation_service/transports/rest.py index d173c1a79509..b3eae0c09863 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/recommendation_service/transports/rest.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/recommendation_service/transports/rest.py @@ -438,6 +438,10 @@ def __call__( "method": "get", "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*/operations/*}", }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/evaluations/*/operations/*}", + }, { "method": "get", "uri": "/v1alpha/{name=projects/*/locations/*/operations/*}", diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/schema_service/transports/rest.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/schema_service/transports/rest.py index 8ff9d41ed798..f64580bf219e 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/schema_service/transports/rest.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/schema_service/transports/rest.py @@ -435,6 +435,10 @@ def operations_client(self) -> operations_v1.AbstractOperationsClient: "method": "get", "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*/operations/*}", }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/evaluations/*/operations/*}", + }, { "method": "get", "uri": "/v1alpha/{name=projects/*/locations/*/operations/*}", @@ -1118,6 +1122,10 @@ def __call__( "method": "get", "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*/operations/*}", }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/evaluations/*/operations/*}", + }, { "method": "get", "uri": "/v1alpha/{name=projects/*/locations/*/operations/*}", diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/search_service/transports/rest.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/search_service/transports/rest.py index 0af3a99d2950..9c5be5135af1 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/search_service/transports/rest.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/search_service/transports/rest.py @@ -436,6 +436,10 @@ def __call__( "method": "get", "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*/operations/*}", }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/evaluations/*/operations/*}", + }, { "method": "get", "uri": "/v1alpha/{name=projects/*/locations/*/operations/*}", diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/search_tuning_service/transports/rest.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/search_tuning_service/transports/rest.py index 7e71bd4789a4..71e5ae9679d5 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/search_tuning_service/transports/rest.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/search_tuning_service/transports/rest.py @@ -314,6 +314,10 @@ def operations_client(self) -> operations_v1.AbstractOperationsClient: "method": "get", "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*/operations/*}", }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/evaluations/*/operations/*}", + }, { "method": "get", "uri": "/v1alpha/{name=projects/*/locations/*/operations/*}", @@ -583,6 +587,10 @@ def __call__( "method": "get", "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*/operations/*}", }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/evaluations/*/operations/*}", + }, { "method": "get", "uri": "/v1alpha/{name=projects/*/locations/*/operations/*}", diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/serving_config_service/async_client.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/serving_config_service/async_client.py index d646f0b5417a..7891ec8832cf 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/serving_config_service/async_client.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/serving_config_service/async_client.py @@ -61,7 +61,9 @@ class ServingConfigServiceAsyncClient: - """Service for operations related to [ServingConfig][].""" + """Service for operations related to + [ServingConfig][google.cloud.discoveryengine.v1alpha.ServingConfig]. + """ _client: ServingConfigServiceClient @@ -300,7 +302,7 @@ async def sample_update_serving_config(): serving_config = discoveryengine_v1alpha.ServingConfig() serving_config.media_config.content_watched_percentage_threshold = 0.3811 serving_config.display_name = "display_name_value" - serving_config.solution_type = "SOLUTION_TYPE_CHAT" + serving_config.solution_type = "SOLUTION_TYPE_GENERATIVE_CHAT" request = discoveryengine_v1alpha.UpdateServingConfigRequest( serving_config=serving_config, diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/serving_config_service/client.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/serving_config_service/client.py index 537e7ac8f2f8..4ecafa4a418f 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/serving_config_service/client.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/serving_config_service/client.py @@ -104,7 +104,9 @@ def get_transport_class( class ServingConfigServiceClient(metaclass=ServingConfigServiceClientMeta): - """Service for operations related to [ServingConfig][].""" + """Service for operations related to + [ServingConfig][google.cloud.discoveryengine.v1alpha.ServingConfig]. + """ @staticmethod def _get_default_mtls_endpoint(api_endpoint): @@ -712,7 +714,7 @@ def sample_update_serving_config(): serving_config = discoveryengine_v1alpha.ServingConfig() serving_config.media_config.content_watched_percentage_threshold = 0.3811 serving_config.display_name = "display_name_value" - serving_config.solution_type = "SOLUTION_TYPE_CHAT" + serving_config.solution_type = "SOLUTION_TYPE_GENERATIVE_CHAT" request = discoveryengine_v1alpha.UpdateServingConfigRequest( serving_config=serving_config, diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/serving_config_service/transports/grpc.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/serving_config_service/transports/grpc.py index 92acf5ade2f1..7510879650fa 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/serving_config_service/transports/grpc.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/serving_config_service/transports/grpc.py @@ -36,7 +36,8 @@ class ServingConfigServiceGrpcTransport(ServingConfigServiceTransport): """gRPC backend transport for ServingConfigService. - Service for operations related to [ServingConfig][]. + Service for operations related to + [ServingConfig][google.cloud.discoveryengine.v1alpha.ServingConfig]. This class defines the same methods as the primary client, so the primary client can load the underlying transport implementation diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/serving_config_service/transports/grpc_asyncio.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/serving_config_service/transports/grpc_asyncio.py index 1b6f1a481c23..ac0370f4d030 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/serving_config_service/transports/grpc_asyncio.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/serving_config_service/transports/grpc_asyncio.py @@ -37,7 +37,8 @@ class ServingConfigServiceGrpcAsyncIOTransport(ServingConfigServiceTransport): """gRPC AsyncIO backend transport for ServingConfigService. - Service for operations related to [ServingConfig][]. + Service for operations related to + [ServingConfig][google.cloud.discoveryengine.v1alpha.ServingConfig]. This class defines the same methods as the primary client, so the primary client can load the underlying transport implementation diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/serving_config_service/transports/rest.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/serving_config_service/transports/rest.py index 2ee2059e4829..c1818764bf5b 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/serving_config_service/transports/rest.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/serving_config_service/transports/rest.py @@ -232,7 +232,8 @@ class ServingConfigServiceRestStub: class ServingConfigServiceRestTransport(ServingConfigServiceTransport): """REST backend transport for ServingConfigService. - Service for operations related to [ServingConfig][]. + Service for operations related to + [ServingConfig][google.cloud.discoveryengine.v1alpha.ServingConfig]. This class defines the same methods as the primary client, so the primary client can load the underlying transport implementation @@ -737,6 +738,10 @@ def __call__( "method": "get", "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*/operations/*}", }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/evaluations/*/operations/*}", + }, { "method": "get", "uri": "/v1alpha/{name=projects/*/locations/*/operations/*}", diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/site_search_engine_service/transports/rest.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/site_search_engine_service/transports/rest.py index eecb33082934..1a3f8294ff31 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/site_search_engine_service/transports/rest.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/site_search_engine_service/transports/rest.py @@ -685,6 +685,10 @@ def operations_client(self) -> operations_v1.AbstractOperationsClient: "method": "get", "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*/operations/*}", }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/evaluations/*/operations/*}", + }, { "method": "get", "uri": "/v1alpha/{name=projects/*/locations/*/operations/*}", @@ -2174,6 +2178,10 @@ def __call__( "method": "get", "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*/operations/*}", }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/evaluations/*/operations/*}", + }, { "method": "get", "uri": "/v1alpha/{name=projects/*/locations/*/operations/*}", diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/user_event_service/transports/rest.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/user_event_service/transports/rest.py index 1462db92b57e..2be9f70f7f63 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/user_event_service/transports/rest.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/services/user_event_service/transports/rest.py @@ -412,6 +412,10 @@ def operations_client(self) -> operations_v1.AbstractOperationsClient: "method": "get", "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*/operations/*}", }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/evaluations/*/operations/*}", + }, { "method": "get", "uri": "/v1alpha/{name=projects/*/locations/*/operations/*}", @@ -1055,6 +1059,10 @@ def __call__( "method": "get", "uri": "/v1alpha/{name=projects/*/locations/*/dataStores/*/operations/*}", }, + { + "method": "get", + "uri": "/v1alpha/{name=projects/*/locations/*/evaluations/*/operations/*}", + }, { "method": "get", "uri": "/v1alpha/{name=projects/*/locations/*/operations/*}", diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/__init__.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/__init__.py index 413667215f6e..2a7475ecb409 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/__init__.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/__init__.py @@ -15,6 +15,7 @@ # from .acl_config import AclConfig from .acl_config_service import GetAclConfigRequest, UpdateAclConfigRequest +from .answer import Answer from .chunk import Chunk from .chunk_service import GetChunkRequest, ListChunksRequest, ListChunksResponse from .common import ( @@ -42,14 +43,23 @@ TextInput, ) from .conversational_search_service import ( + AnswerQueryRequest, + AnswerQueryResponse, ConverseConversationRequest, ConverseConversationResponse, CreateConversationRequest, + CreateSessionRequest, DeleteConversationRequest, + DeleteSessionRequest, + GetAnswerRequest, GetConversationRequest, + GetSessionRequest, ListConversationsRequest, ListConversationsResponse, + ListSessionsRequest, + ListSessionsResponse, UpdateConversationRequest, + UpdateSessionRequest, ) from .data_store import DataStore from .data_store_service import ( @@ -64,12 +74,13 @@ UpdateDataStoreRequest, UpdateDocumentProcessingConfigRequest, ) -from .document import Document +from .document import Document, ProcessedDocument from .document_processing_config import DocumentProcessingConfig from .document_service import ( CreateDocumentRequest, DeleteDocumentRequest, GetDocumentRequest, + GetProcessedDocumentRequest, ListDocumentsRequest, ListDocumentsResponse, UpdateDocumentRequest, @@ -95,8 +106,19 @@ EstimateDataSizeRequest, EstimateDataSizeResponse, ) +from .grounded_generation_service import ( + CheckGroundingRequest, + CheckGroundingResponse, + CheckGroundingSpec, +) +from .grounding import FactChunk, GroundingFact from .import_config import ( BigQuerySource, + BigtableOptions, + BigtableSource, + CloudSqlSource, + FhirStoreSource, + FirestoreSource, GcsSource, ImportDocumentsMetadata, ImportDocumentsRequest, @@ -108,6 +130,14 @@ ImportUserEventsMetadata, ImportUserEventsRequest, ImportUserEventsResponse, + SpannerSource, +) +from .project import Project +from .project_service import ( + GetProjectRequest, + ProvisionProjectMetadata, + ProvisionProjectRequest, + ReportConsentChangeRequest, ) from .purge_config import ( PurgeDocumentsMetadata, @@ -121,6 +151,7 @@ PurgeUserEventsRequest, PurgeUserEventsResponse, ) +from .rank_service import RankingRecord, RankRequest, RankResponse from .recommendation_service import RecommendRequest, RecommendResponse from .schema import FieldConfig, Schema from .schema_service import ( @@ -147,6 +178,7 @@ ListServingConfigsResponse, UpdateServingConfigRequest, ) +from .session import Query, Session from .site_search_engine import SiteSearchEngine, SiteVerificationInfo, TargetSite from .site_search_engine_service import ( BatchCreateTargetSiteMetadata, @@ -193,6 +225,7 @@ "AclConfig", "GetAclConfigRequest", "UpdateAclConfigRequest", + "Answer", "Chunk", "GetChunkRequest", "ListChunksRequest", @@ -218,14 +251,23 @@ "ConversationMessage", "Reply", "TextInput", + "AnswerQueryRequest", + "AnswerQueryResponse", "ConverseConversationRequest", "ConverseConversationResponse", "CreateConversationRequest", + "CreateSessionRequest", "DeleteConversationRequest", + "DeleteSessionRequest", + "GetAnswerRequest", "GetConversationRequest", + "GetSessionRequest", "ListConversationsRequest", "ListConversationsResponse", + "ListSessionsRequest", + "ListSessionsResponse", "UpdateConversationRequest", + "UpdateSessionRequest", "DataStore", "CreateDataStoreMetadata", "CreateDataStoreRequest", @@ -238,10 +280,12 @@ "UpdateDataStoreRequest", "UpdateDocumentProcessingConfigRequest", "Document", + "ProcessedDocument", "DocumentProcessingConfig", "CreateDocumentRequest", "DeleteDocumentRequest", "GetDocumentRequest", + "GetProcessedDocumentRequest", "ListDocumentsRequest", "ListDocumentsResponse", "UpdateDocumentRequest", @@ -262,7 +306,17 @@ "EstimateDataSizeMetadata", "EstimateDataSizeRequest", "EstimateDataSizeResponse", + "CheckGroundingRequest", + "CheckGroundingResponse", + "CheckGroundingSpec", + "FactChunk", + "GroundingFact", "BigQuerySource", + "BigtableOptions", + "BigtableSource", + "CloudSqlSource", + "FhirStoreSource", + "FirestoreSource", "GcsSource", "ImportDocumentsMetadata", "ImportDocumentsRequest", @@ -274,6 +328,12 @@ "ImportUserEventsMetadata", "ImportUserEventsRequest", "ImportUserEventsResponse", + "SpannerSource", + "Project", + "GetProjectRequest", + "ProvisionProjectMetadata", + "ProvisionProjectRequest", + "ReportConsentChangeRequest", "PurgeDocumentsMetadata", "PurgeDocumentsRequest", "PurgeDocumentsResponse", @@ -284,6 +344,9 @@ "PurgeUserEventsMetadata", "PurgeUserEventsRequest", "PurgeUserEventsResponse", + "RankingRecord", + "RankRequest", + "RankResponse", "RecommendRequest", "RecommendResponse", "FieldConfig", @@ -307,6 +370,8 @@ "ListServingConfigsRequest", "ListServingConfigsResponse", "UpdateServingConfigRequest", + "Query", + "Session", "SiteSearchEngine", "SiteVerificationInfo", "TargetSite", diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/answer.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/answer.py new file mode 100644 index 000000000000..ce69b8fb477d --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/answer.py @@ -0,0 +1,619 @@ +# -*- 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 timestamp_pb2 # type: ignore +import proto # type: ignore + +__protobuf__ = proto.module( + package="google.cloud.discoveryengine.v1alpha", + manifest={ + "Answer", + }, +) + + +class Answer(proto.Message): + r"""Defines an answer. + + Attributes: + name (str): + Immutable. Fully qualified name + ``projects/{project}/locations/global/collections/{collection}/engines/{engine}/sessions/*/answers/*`` + state (google.cloud.discoveryengine_v1alpha.types.Answer.State): + The state of the answer generation. + answer_text (str): + The textual answer. + citations (MutableSequence[google.cloud.discoveryengine_v1alpha.types.Answer.Citation]): + Citations. + references (MutableSequence[google.cloud.discoveryengine_v1alpha.types.Answer.Reference]): + References. + related_questions (MutableSequence[str]): + Suggested related questions. + steps (MutableSequence[google.cloud.discoveryengine_v1alpha.types.Answer.Step]): + Answer generation steps. + query_understanding_info (google.cloud.discoveryengine_v1alpha.types.Answer.QueryUnderstandingInfo): + Query understanding information. + answer_skipped_reasons (MutableSequence[google.cloud.discoveryengine_v1alpha.types.Answer.AnswerSkippedReason]): + Additional answer-skipped reasons. This + provides the reason for ignored cases. If + nothing is skipped, this field is not set. + create_time (google.protobuf.timestamp_pb2.Timestamp): + Output only. Answer creation timestamp. + complete_time (google.protobuf.timestamp_pb2.Timestamp): + Output only. Answer completed timestamp. + """ + + class State(proto.Enum): + r"""Enumeration of the state of the answer generation. + + Values: + STATE_UNSPECIFIED (0): + Unknown. + IN_PROGRESS (1): + Answer generation is currently in progress. + FAILED (2): + Answer generation currently failed. + SUCCEEDED (3): + Answer generation has succeeded. + """ + STATE_UNSPECIFIED = 0 + IN_PROGRESS = 1 + FAILED = 2 + SUCCEEDED = 3 + + class AnswerSkippedReason(proto.Enum): + r"""An enum for answer skipped reasons. + + Values: + ANSWER_SKIPPED_REASON_UNSPECIFIED (0): + Default value. The answer skipped reason is + not specified. + ADVERSARIAL_QUERY_IGNORED (1): + The adversarial query ignored case. + NON_ANSWER_SEEKING_QUERY_IGNORED (2): + The non-answer seeking query ignored case. + OUT_OF_DOMAIN_QUERY_IGNORED (3): + The out-of-domain query ignored case. + + Google skips the answer if there are no + high-relevance search results. + POTENTIAL_POLICY_VIOLATION (4): + The potential policy violation case. + + Google skips the answer if there is a potential + policy violation detected. This includes content + that may be violent or toxic. + """ + ANSWER_SKIPPED_REASON_UNSPECIFIED = 0 + ADVERSARIAL_QUERY_IGNORED = 1 + NON_ANSWER_SEEKING_QUERY_IGNORED = 2 + OUT_OF_DOMAIN_QUERY_IGNORED = 3 + POTENTIAL_POLICY_VIOLATION = 4 + + class Citation(proto.Message): + r"""Citation info for a segment. + + Attributes: + start_index (int): + Index indicates the start of the segment, + measured in bytes (UTF-8 unicode). + end_index (int): + End of the attributed segment, exclusive. + sources (MutableSequence[google.cloud.discoveryengine_v1alpha.types.Answer.CitationSource]): + Citation sources for the attributed segment. + """ + + start_index: int = proto.Field( + proto.INT64, + number=1, + ) + end_index: int = proto.Field( + proto.INT64, + number=2, + ) + sources: MutableSequence["Answer.CitationSource"] = proto.RepeatedField( + proto.MESSAGE, + number=3, + message="Answer.CitationSource", + ) + + class CitationSource(proto.Message): + r"""Citation source. + + Attributes: + reference_id (str): + ID of the citation source. + """ + + reference_id: str = proto.Field( + proto.STRING, + number=1, + ) + + class Reference(proto.Message): + r"""Reference. + + 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: + unstructured_document_info (google.cloud.discoveryengine_v1alpha.types.Answer.Reference.UnstructuredDocumentInfo): + Unstructured document information. + + This field is a member of `oneof`_ ``content``. + chunk_info (google.cloud.discoveryengine_v1alpha.types.Answer.Reference.ChunkInfo): + Chunk information. + + This field is a member of `oneof`_ ``content``. + """ + + class UnstructuredDocumentInfo(proto.Message): + r"""Unstructured document information. + + Attributes: + document (str): + Document resource name. + uri (str): + URI for the document. + title (str): + Title. + chunk_contents (MutableSequence[google.cloud.discoveryengine_v1alpha.types.Answer.Reference.UnstructuredDocumentInfo.ChunkContent]): + List of cited chunk contents derived from + document content. + """ + + class ChunkContent(proto.Message): + r"""Chunk content. + + Attributes: + content (str): + Chunk textual content. + page_identifier (str): + Page identifier. + """ + + content: str = proto.Field( + proto.STRING, + number=1, + ) + page_identifier: str = proto.Field( + proto.STRING, + number=2, + ) + + document: str = proto.Field( + proto.STRING, + number=1, + ) + uri: str = proto.Field( + proto.STRING, + number=2, + ) + title: str = proto.Field( + proto.STRING, + number=3, + ) + chunk_contents: MutableSequence[ + "Answer.Reference.UnstructuredDocumentInfo.ChunkContent" + ] = proto.RepeatedField( + proto.MESSAGE, + number=4, + message="Answer.Reference.UnstructuredDocumentInfo.ChunkContent", + ) + + class ChunkInfo(proto.Message): + r"""Chunk information. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + chunk (str): + Chunk resource name. + content (str): + Chunk textual content. + relevance_score (float): + Relevance score. + + This field is a member of `oneof`_ ``_relevance_score``. + document_metadata (google.cloud.discoveryengine_v1alpha.types.Answer.Reference.ChunkInfo.DocumentMetadata): + Document metadata. + """ + + class DocumentMetadata(proto.Message): + r"""Document metadata. + + Attributes: + document (str): + Document resource name. + uri (str): + URI for the document. + title (str): + Title. + page_identifier (str): + Page identifier. + """ + + document: str = proto.Field( + proto.STRING, + number=1, + ) + uri: str = proto.Field( + proto.STRING, + number=2, + ) + title: str = proto.Field( + proto.STRING, + number=3, + ) + page_identifier: str = proto.Field( + proto.STRING, + number=4, + ) + + chunk: str = proto.Field( + proto.STRING, + number=1, + ) + content: str = proto.Field( + proto.STRING, + number=2, + ) + relevance_score: float = proto.Field( + proto.FLOAT, + number=3, + optional=True, + ) + document_metadata: "Answer.Reference.ChunkInfo.DocumentMetadata" = ( + proto.Field( + proto.MESSAGE, + number=4, + message="Answer.Reference.ChunkInfo.DocumentMetadata", + ) + ) + + unstructured_document_info: "Answer.Reference.UnstructuredDocumentInfo" = ( + proto.Field( + proto.MESSAGE, + number=1, + oneof="content", + message="Answer.Reference.UnstructuredDocumentInfo", + ) + ) + chunk_info: "Answer.Reference.ChunkInfo" = proto.Field( + proto.MESSAGE, + number=2, + oneof="content", + message="Answer.Reference.ChunkInfo", + ) + + class Step(proto.Message): + r"""Step information. + + Attributes: + state (google.cloud.discoveryengine_v1alpha.types.Answer.Step.State): + The state of the step. + description (str): + The description of the step. + thought (str): + The thought of the step. + actions (MutableSequence[google.cloud.discoveryengine_v1alpha.types.Answer.Step.Action]): + Actions. + """ + + class State(proto.Enum): + r"""Enumeration of the state of the step. + + Values: + STATE_UNSPECIFIED (0): + Unknown. + IN_PROGRESS (1): + Step is currently in progress. + FAILED (2): + Step currently failed. + SUCCEEDED (3): + Step has succeeded. + """ + STATE_UNSPECIFIED = 0 + IN_PROGRESS = 1 + FAILED = 2 + SUCCEEDED = 3 + + class Action(proto.Message): + r"""Action. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + search_action (google.cloud.discoveryengine_v1alpha.types.Answer.Step.Action.SearchAction): + Search action. + + This field is a member of `oneof`_ ``action``. + observation (google.cloud.discoveryengine_v1alpha.types.Answer.Step.Action.Observation): + Observation. + """ + + class SearchAction(proto.Message): + r"""Search action. + + Attributes: + query (str): + The query to search. + """ + + query: str = proto.Field( + proto.STRING, + number=1, + ) + + class Observation(proto.Message): + r"""Observation. + + Attributes: + search_results (MutableSequence[google.cloud.discoveryengine_v1alpha.types.Answer.Step.Action.Observation.SearchResult]): + Search results observed by the search action, + it can be snippets info or chunk info, depending + on the citation type set by the user. + """ + + class SearchResult(proto.Message): + r""" + + Attributes: + document (str): + Document resource name. + uri (str): + URI for the document. + title (str): + Title. + snippet_info (MutableSequence[google.cloud.discoveryengine_v1alpha.types.Answer.Step.Action.Observation.SearchResult.SnippetInfo]): + If citation_type is DOCUMENT_LEVEL_CITATION, populate + document level snippets. + chunk_info (MutableSequence[google.cloud.discoveryengine_v1alpha.types.Answer.Step.Action.Observation.SearchResult.ChunkInfo]): + If citation_type is CHUNK_LEVEL_CITATION and chunk mode is + on, populate chunk info. + """ + + class SnippetInfo(proto.Message): + r"""Snippet information. + + Attributes: + snippet (str): + Snippet content. + snippet_status (str): + Status of the snippet defined by the search + team. + """ + + snippet: str = proto.Field( + proto.STRING, + number=1, + ) + snippet_status: str = proto.Field( + proto.STRING, + number=2, + ) + + class ChunkInfo(proto.Message): + r"""Chunk information. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + chunk (str): + Chunk resource name. + content (str): + Chunk textual content. + relevance_score (float): + Relevance score. + + This field is a member of `oneof`_ ``_relevance_score``. + """ + + chunk: str = proto.Field( + proto.STRING, + number=1, + ) + content: str = proto.Field( + proto.STRING, + number=2, + ) + relevance_score: float = proto.Field( + proto.FLOAT, + number=3, + optional=True, + ) + + document: str = proto.Field( + proto.STRING, + number=1, + ) + uri: str = proto.Field( + proto.STRING, + number=2, + ) + title: str = proto.Field( + proto.STRING, + number=3, + ) + snippet_info: MutableSequence[ + "Answer.Step.Action.Observation.SearchResult.SnippetInfo" + ] = proto.RepeatedField( + proto.MESSAGE, + number=4, + message="Answer.Step.Action.Observation.SearchResult.SnippetInfo", + ) + chunk_info: MutableSequence[ + "Answer.Step.Action.Observation.SearchResult.ChunkInfo" + ] = proto.RepeatedField( + proto.MESSAGE, + number=5, + message="Answer.Step.Action.Observation.SearchResult.ChunkInfo", + ) + + search_results: MutableSequence[ + "Answer.Step.Action.Observation.SearchResult" + ] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="Answer.Step.Action.Observation.SearchResult", + ) + + search_action: "Answer.Step.Action.SearchAction" = proto.Field( + proto.MESSAGE, + number=2, + oneof="action", + message="Answer.Step.Action.SearchAction", + ) + observation: "Answer.Step.Action.Observation" = proto.Field( + proto.MESSAGE, + number=3, + message="Answer.Step.Action.Observation", + ) + + state: "Answer.Step.State" = proto.Field( + proto.ENUM, + number=1, + enum="Answer.Step.State", + ) + description: str = proto.Field( + proto.STRING, + number=2, + ) + thought: str = proto.Field( + proto.STRING, + number=3, + ) + actions: MutableSequence["Answer.Step.Action"] = proto.RepeatedField( + proto.MESSAGE, + number=4, + message="Answer.Step.Action", + ) + + class QueryUnderstandingInfo(proto.Message): + r"""Query understanding information. + + Attributes: + query_classification_info (MutableSequence[google.cloud.discoveryengine_v1alpha.types.Answer.QueryUnderstandingInfo.QueryClassificationInfo]): + Query classification information. + """ + + class QueryClassificationInfo(proto.Message): + r"""Query classification information. + + Attributes: + type_ (google.cloud.discoveryengine_v1alpha.types.Answer.QueryUnderstandingInfo.QueryClassificationInfo.Type): + Query classification type. + positive (bool): + Classification output. + """ + + class Type(proto.Enum): + r"""Query classification types. + + Values: + TYPE_UNSPECIFIED (0): + Unspecified query classification type. + ADVERSARIAL_QUERY (1): + Adversarial query classification type. + NON_ANSWER_SEEKING_QUERY (2): + Non-answer-seeking query classification type. + """ + TYPE_UNSPECIFIED = 0 + ADVERSARIAL_QUERY = 1 + NON_ANSWER_SEEKING_QUERY = 2 + + type_: "Answer.QueryUnderstandingInfo.QueryClassificationInfo.Type" = ( + proto.Field( + proto.ENUM, + number=1, + enum="Answer.QueryUnderstandingInfo.QueryClassificationInfo.Type", + ) + ) + positive: bool = proto.Field( + proto.BOOL, + number=2, + ) + + query_classification_info: MutableSequence[ + "Answer.QueryUnderstandingInfo.QueryClassificationInfo" + ] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="Answer.QueryUnderstandingInfo.QueryClassificationInfo", + ) + + name: str = proto.Field( + proto.STRING, + number=1, + ) + state: State = proto.Field( + proto.ENUM, + number=2, + enum=State, + ) + answer_text: str = proto.Field( + proto.STRING, + number=3, + ) + citations: MutableSequence[Citation] = proto.RepeatedField( + proto.MESSAGE, + number=4, + message=Citation, + ) + references: MutableSequence[Reference] = proto.RepeatedField( + proto.MESSAGE, + number=5, + message=Reference, + ) + related_questions: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=6, + ) + steps: MutableSequence[Step] = proto.RepeatedField( + proto.MESSAGE, + number=7, + message=Step, + ) + query_understanding_info: QueryUnderstandingInfo = proto.Field( + proto.MESSAGE, + number=10, + message=QueryUnderstandingInfo, + ) + answer_skipped_reasons: MutableSequence[AnswerSkippedReason] = proto.RepeatedField( + proto.ENUM, + number=11, + enum=AnswerSkippedReason, + ) + create_time: timestamp_pb2.Timestamp = proto.Field( + proto.MESSAGE, + number=8, + message=timestamp_pb2.Timestamp, + ) + complete_time: timestamp_pb2.Timestamp = proto.Field( + proto.MESSAGE, + number=9, + message=timestamp_pb2.Timestamp, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/chunk.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/chunk.py index c7dc880260f0..c439f6ed7dc4 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/chunk.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/chunk.py @@ -40,7 +40,7 @@ class Chunk(proto.Message): This field must be a UTF-8 encoded string with a length limit of 1024 characters. id (str): - Unique chunk id of the current chunk. + Unique chunk ID of the current chunk. content (str): Content is a string from a document (parsed content). @@ -50,6 +50,10 @@ class Chunk(proto.Message): derived_struct_data (google.protobuf.struct_pb2.Struct): Output only. This field is OUTPUT_ONLY. It contains derived data that are not in the original input document. + page_span (google.cloud.discoveryengine_v1alpha.types.Chunk.PageSpan): + Page span of the chunk. + chunk_metadata (google.cloud.discoveryengine_v1alpha.types.Chunk.ChunkMetadata): + Output only. Metadata of the current chunk. """ class DocumentMetadata(proto.Message): @@ -61,6 +65,11 @@ class DocumentMetadata(proto.Message): Uri of the document. title (str): Title of the document. + struct_data (google.protobuf.struct_pb2.Struct): + Data representation. The structured JSON data for the + document. It should conform to the registered + [Schema][google.cloud.discoveryengine.v1alpha.Schema] or an + ``INVALID_ARGUMENT`` error is thrown. """ uri: str = proto.Field( @@ -71,6 +80,63 @@ class DocumentMetadata(proto.Message): proto.STRING, number=2, ) + struct_data: struct_pb2.Struct = proto.Field( + proto.MESSAGE, + number=3, + message=struct_pb2.Struct, + ) + + class PageSpan(proto.Message): + r"""Page span of the chunk. + + Attributes: + page_start (int): + The start page of the chunk. + page_end (int): + The end page of the chunk. + """ + + page_start: int = proto.Field( + proto.INT32, + number=1, + ) + page_end: int = proto.Field( + proto.INT32, + number=2, + ) + + class ChunkMetadata(proto.Message): + r"""Metadata of the current chunk. This field is only populated on + [SearchService.Search][google.cloud.discoveryengine.v1alpha.SearchService.Search] + API. + + Attributes: + previous_chunks (MutableSequence[google.cloud.discoveryengine_v1alpha.types.Chunk]): + The previous chunks of the current chunk. The number is + controlled by + [SearchRequest.ContentSearchSpec.ChunkSpec.num_previous_chunks][google.cloud.discoveryengine.v1alpha.SearchRequest.ContentSearchSpec.ChunkSpec.num_previous_chunks]. + This field is only populated on + [SearchService.Search][google.cloud.discoveryengine.v1alpha.SearchService.Search] + API. + next_chunks (MutableSequence[google.cloud.discoveryengine_v1alpha.types.Chunk]): + The next chunks of the current chunk. The number is + controlled by + [SearchRequest.ContentSearchSpec.ChunkSpec.num_next_chunks][google.cloud.discoveryengine.v1alpha.SearchRequest.ContentSearchSpec.ChunkSpec.num_next_chunks]. + This field is only populated on + [SearchService.Search][google.cloud.discoveryengine.v1alpha.SearchService.Search] + API. + """ + + previous_chunks: MutableSequence["Chunk"] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="Chunk", + ) + next_chunks: MutableSequence["Chunk"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="Chunk", + ) name: str = proto.Field( proto.STRING, @@ -94,6 +160,16 @@ class DocumentMetadata(proto.Message): number=4, message=struct_pb2.Struct, ) + page_span: PageSpan = proto.Field( + proto.MESSAGE, + number=6, + message=PageSpan, + ) + chunk_metadata: ChunkMetadata = proto.Field( + proto.MESSAGE, + number=7, + message=ChunkMetadata, + ) __all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/common.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/common.py index d749dbe770bd..09db19e279da 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/common.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/common.py @@ -51,10 +51,13 @@ class IndustryVertical(proto.Enum): not specific to any industry vertical. MEDIA (2): The media industry vertical. + HEALTHCARE_FHIR (7): + The healthcare FHIR vertical. """ INDUSTRY_VERTICAL_UNSPECIFIED = 0 GENERIC = 1 MEDIA = 2 + HEALTHCARE_FHIR = 7 class SolutionType(proto.Enum): @@ -70,16 +73,22 @@ class SolutionType(proto.Enum): SOLUTION_TYPE_CHAT (3): Used for use cases related to the Generative AI agent. + SOLUTION_TYPE_GENERATIVE_CHAT (4): + Used for use cases related to the Generative Chat agent. + It's used for Generative chat engine only, the associated + data stores must enrolled with ``SOLUTION_TYPE_CHAT`` + solution. """ SOLUTION_TYPE_UNSPECIFIED = 0 SOLUTION_TYPE_RECOMMENDATION = 1 SOLUTION_TYPE_SEARCH = 2 SOLUTION_TYPE_CHAT = 3 + SOLUTION_TYPE_GENERATIVE_CHAT = 4 class SearchTier(proto.Enum): r"""Tiers of search features. Different tiers might have - different pricing. To learn more, please check the pricing + different pricing. To learn more, check the pricing documentation. Values: diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/conversational_search_service.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/conversational_search_service.py index 97826695caf2..a21924344206 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/conversational_search_service.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/conversational_search_service.py @@ -21,7 +21,10 @@ import proto # type: ignore from google.cloud.discoveryengine_v1alpha.types import conversation as gcd_conversation +from google.cloud.discoveryengine_v1alpha.types import answer as gcd_answer +from google.cloud.discoveryengine_v1alpha.types import common from google.cloud.discoveryengine_v1alpha.types import search_service +from google.cloud.discoveryengine_v1alpha.types import session as gcd_session __protobuf__ = proto.module( package="google.cloud.discoveryengine.v1alpha", @@ -34,6 +37,15 @@ "GetConversationRequest", "ListConversationsRequest", "ListConversationsResponse", + "AnswerQueryRequest", + "AnswerQueryResponse", + "GetAnswerRequest", + "CreateSessionRequest", + "UpdateSessionRequest", + "DeleteSessionRequest", + "GetSessionRequest", + "ListSessionsRequest", + "ListSessionsResponse", }, ) @@ -362,4 +374,817 @@ def raw_page(self): ) +class AnswerQueryRequest(proto.Message): + r"""Request message for + [ConversationalSearchService.AnswerQuery][google.cloud.discoveryengine.v1alpha.ConversationalSearchService.AnswerQuery] + method. + + Attributes: + serving_config (str): + Required. The resource name of the Search serving config, + such as + ``projects/*/locations/global/collections/default_collection/engines/*/servingConfigs/default_serving_config``, + or + ``projects/*/locations/global/collections/default_collection/dataStores/*/servingConfigs/default_serving_config``. + This field is used to identify the serving configuration + name, set of models used to make the search. + query (google.cloud.discoveryengine_v1alpha.types.Query): + Required. Current user query. + session (str): + The session resource name. Not required. + + When session field is not set, the API is in + sessionless mode. + + We support auto session mode: users can use the + wildcard symbol “-” as session id. A new id + will be automatically generated and assigned. + safety_spec (google.cloud.discoveryengine_v1alpha.types.AnswerQueryRequest.SafetySpec): + Model specification. + related_questions_spec (google.cloud.discoveryengine_v1alpha.types.AnswerQueryRequest.RelatedQuestionsSpec): + Related questions specification. + answer_generation_spec (google.cloud.discoveryengine_v1alpha.types.AnswerQueryRequest.AnswerGenerationSpec): + Answer generation specification. + search_spec (google.cloud.discoveryengine_v1alpha.types.AnswerQueryRequest.SearchSpec): + Search specification. + query_understanding_spec (google.cloud.discoveryengine_v1alpha.types.AnswerQueryRequest.QueryUnderstandingSpec): + Query understanding specification. + asynchronous_mode (bool): + Asynchronous mode control. + + If enabled, the response will be returned with + answer/session resource name without final answer. The API + users need to do the polling to get the latest status of + answer/session by calling + [ConversationalSearchService.GetAnswer][google.cloud.discoveryengine.v1alpha.ConversationalSearchService.GetAnswer] + or + [ConversationalSearchService.GetSession][google.cloud.discoveryengine.v1alpha.ConversationalSearchService.GetSession] + method. + user_pseudo_id (str): + A unique identifier for tracking visitors. For example, this + could be implemented with an HTTP cookie, which should be + able to uniquely identify a visitor on a single device. This + unique identifier should not change if the visitor logs in + or out of the website. + + This field should NOT have a fixed value such as + ``unknown_visitor``. + + The field must be a UTF-8 encoded string with a length limit + of 128 characters. Otherwise, an ``INVALID_ARGUMENT`` error + is returned. + """ + + class SafetySpec(proto.Message): + r"""Safety specification. + + Attributes: + enable (bool): + Enable the safety filtering on the answer + response. It is false by default. + """ + + enable: bool = proto.Field( + proto.BOOL, + number=1, + ) + + class RelatedQuestionsSpec(proto.Message): + r"""Related questions specification. + + Attributes: + enable (bool): + Enable related questions feature if true. + """ + + enable: bool = proto.Field( + proto.BOOL, + number=1, + ) + + class AnswerGenerationSpec(proto.Message): + r"""Answer generation specification. + + Attributes: + model_spec (google.cloud.discoveryengine_v1alpha.types.AnswerQueryRequest.AnswerGenerationSpec.ModelSpec): + Answer generation model specification. + prompt_spec (google.cloud.discoveryengine_v1alpha.types.AnswerQueryRequest.AnswerGenerationSpec.PromptSpec): + Answer generation prompt specification. + include_citations (bool): + Specifies whether to include citation metadata in the + answer. The default value is ``false``. + answer_language_code (str): + Language code for Answer. Use language tags defined by + `BCP47 `__. + Note: This is an experimental feature. + ignore_adversarial_query (bool): + Specifies whether to filter out adversarial queries. The + default value is ``false``. + + Google employs search-query classification to detect + adversarial queries. No answer is returned if the search + query is classified as an adversarial query. For example, a + user might ask a question regarding negative comments about + the company or submit a query designed to generate unsafe, + policy-violating output. If this field is set to ``true``, + we skip generating answers for adversarial queries and + return fallback messages instead. + ignore_non_answer_seeking_query (bool): + Specifies whether to filter out queries that are not + answer-seeking. The default value is ``false``. + + Google employs search-query classification to detect + answer-seeking queries. No answer is returned if the search + query is classified as a non-answer seeking query. If this + field is set to ``true``, we skip generating answers for + non-answer seeking queries and return fallback messages + instead. + """ + + class ModelSpec(proto.Message): + r"""Answer Generation Model specification. + + Attributes: + model_version (str): + Model version. If not set, it will use the + default stable model. Allowed values are: + stable, preview. + """ + + model_version: str = proto.Field( + proto.STRING, + number=1, + ) + + class PromptSpec(proto.Message): + r"""Answer generation prompt specification. + + Attributes: + preamble (str): + Customized preamble. + """ + + preamble: str = proto.Field( + proto.STRING, + number=1, + ) + + model_spec: "AnswerQueryRequest.AnswerGenerationSpec.ModelSpec" = proto.Field( + proto.MESSAGE, + number=1, + message="AnswerQueryRequest.AnswerGenerationSpec.ModelSpec", + ) + prompt_spec: "AnswerQueryRequest.AnswerGenerationSpec.PromptSpec" = proto.Field( + proto.MESSAGE, + number=2, + message="AnswerQueryRequest.AnswerGenerationSpec.PromptSpec", + ) + include_citations: bool = proto.Field( + proto.BOOL, + number=3, + ) + answer_language_code: str = proto.Field( + proto.STRING, + number=4, + ) + ignore_adversarial_query: bool = proto.Field( + proto.BOOL, + number=5, + ) + ignore_non_answer_seeking_query: bool = proto.Field( + proto.BOOL, + number=6, + ) + + class SearchSpec(proto.Message): + r"""Search specification. + + 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: + search_params (google.cloud.discoveryengine_v1alpha.types.AnswerQueryRequest.SearchSpec.SearchParams): + Search parameters. + + This field is a member of `oneof`_ ``input``. + search_result_list (google.cloud.discoveryengine_v1alpha.types.AnswerQueryRequest.SearchSpec.SearchResultList): + Search result list. + + This field is a member of `oneof`_ ``input``. + """ + + class SearchParams(proto.Message): + r"""Search parameters. + + Attributes: + max_return_results (int): + Number of search results to return. + The default value is 10. + filter (str): + The filter syntax consists of an expression language for + constructing a predicate from one or more fields of the + documents being filtered. Filter expression is + case-sensitive. This will be used to filter search results + which may affect the Answer response. + + If this field is unrecognizable, an ``INVALID_ARGUMENT`` is + returned. + + Filtering in Vertex AI Search is done by mapping the LHS + filter key to a key property defined in the Vertex AI Search + backend -- this mapping is defined by the customer in their + schema. For example a media customers might have a field + 'name' in their schema. In this case the filter would look + like this: filter --> name:'ANY("king kong")' + + For more information about filtering including syntax and + filter operators, see + `Filter `__ + boost_spec (google.cloud.discoveryengine_v1alpha.types.SearchRequest.BoostSpec): + Boost specification to boost certain documents in search + results which may affect the answer query response. For more + information on boosting, see + `Boosting `__ + order_by (str): + The order in which documents are returned. Documents can be + ordered by a field in an + [Document][google.cloud.discoveryengine.v1alpha.Document] + object. Leave it unset if ordered by relevance. ``order_by`` + expression is case-sensitive. For more information on + ordering, see + `Ordering `__ + + If this field is unrecognizable, an ``INVALID_ARGUMENT`` is + returned. + search_result_mode (google.cloud.discoveryengine_v1alpha.types.SearchRequest.ContentSearchSpec.SearchResultMode): + Specifies the search result mode. If unspecified, the search + result mode is based on + [DataStore.DocumentProcessingConfig.chunking_config][]: + + - If [DataStore.DocumentProcessingConfig.chunking_config][] + is specified, it defaults to ``CHUNKS``. + - Otherwise, it defaults to ``DOCUMENTS``. See `parse and + chunk + documents `__ + custom_fine_tuning_spec (google.cloud.discoveryengine_v1alpha.types.CustomFineTuningSpec): + Custom fine tuning configs. + """ + + max_return_results: int = proto.Field( + proto.INT32, + number=1, + ) + filter: str = proto.Field( + proto.STRING, + number=2, + ) + boost_spec: search_service.SearchRequest.BoostSpec = proto.Field( + proto.MESSAGE, + number=3, + message=search_service.SearchRequest.BoostSpec, + ) + order_by: str = proto.Field( + proto.STRING, + number=4, + ) + search_result_mode: search_service.SearchRequest.ContentSearchSpec.SearchResultMode = proto.Field( + proto.ENUM, + number=5, + enum=search_service.SearchRequest.ContentSearchSpec.SearchResultMode, + ) + custom_fine_tuning_spec: common.CustomFineTuningSpec = proto.Field( + proto.MESSAGE, + number=6, + message=common.CustomFineTuningSpec, + ) + + class SearchResultList(proto.Message): + r"""Search result list. + + Attributes: + search_results (MutableSequence[google.cloud.discoveryengine_v1alpha.types.AnswerQueryRequest.SearchSpec.SearchResultList.SearchResult]): + Search results. + """ + + class SearchResult(proto.Message): + r"""Search result. + + 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: + unstructured_document_info (google.cloud.discoveryengine_v1alpha.types.AnswerQueryRequest.SearchSpec.SearchResultList.SearchResult.UnstructuredDocumentInfo): + Unstructured document information. + + This field is a member of `oneof`_ ``content``. + chunk_info (google.cloud.discoveryengine_v1alpha.types.AnswerQueryRequest.SearchSpec.SearchResultList.SearchResult.ChunkInfo): + Chunk information. + + This field is a member of `oneof`_ ``content``. + """ + + class UnstructuredDocumentInfo(proto.Message): + r"""Unstructured document information. + + Attributes: + document (str): + Document resource name. + uri (str): + URI for the document. + title (str): + Title. + document_contexts (MutableSequence[google.cloud.discoveryengine_v1alpha.types.AnswerQueryRequest.SearchSpec.SearchResultList.SearchResult.UnstructuredDocumentInfo.DocumentContext]): + List of document contexts. + extractive_segments (MutableSequence[google.cloud.discoveryengine_v1alpha.types.AnswerQueryRequest.SearchSpec.SearchResultList.SearchResult.UnstructuredDocumentInfo.ExtractiveSegment]): + List of extractive segments. + extractive_answers (MutableSequence[google.cloud.discoveryengine_v1alpha.types.AnswerQueryRequest.SearchSpec.SearchResultList.SearchResult.UnstructuredDocumentInfo.ExtractiveAnswer]): + List of extractive answers. + """ + + class DocumentContext(proto.Message): + r"""Document context. + + Attributes: + page_identifier (str): + Page identifier. + content (str): + Document content. + """ + + page_identifier: str = proto.Field( + proto.STRING, + number=1, + ) + content: str = proto.Field( + proto.STRING, + number=2, + ) + + class ExtractiveSegment(proto.Message): + r"""Extractive segment. + `Guide `__ + + Attributes: + page_identifier (str): + Page identifier. + content (str): + Extractive segment content. + """ + + page_identifier: str = proto.Field( + proto.STRING, + number=1, + ) + content: str = proto.Field( + proto.STRING, + number=2, + ) + + class ExtractiveAnswer(proto.Message): + r"""Extractive answer. + `Guide `__ + + Attributes: + page_identifier (str): + Page identifier. + content (str): + Extractive answer content. + """ + + page_identifier: str = proto.Field( + proto.STRING, + number=1, + ) + content: str = proto.Field( + proto.STRING, + number=2, + ) + + document: str = proto.Field( + proto.STRING, + number=1, + ) + uri: str = proto.Field( + proto.STRING, + number=2, + ) + title: str = proto.Field( + proto.STRING, + number=3, + ) + document_contexts: MutableSequence[ + "AnswerQueryRequest.SearchSpec.SearchResultList.SearchResult.UnstructuredDocumentInfo.DocumentContext" + ] = proto.RepeatedField( + proto.MESSAGE, + number=4, + message="AnswerQueryRequest.SearchSpec.SearchResultList.SearchResult.UnstructuredDocumentInfo.DocumentContext", + ) + extractive_segments: MutableSequence[ + "AnswerQueryRequest.SearchSpec.SearchResultList.SearchResult.UnstructuredDocumentInfo.ExtractiveSegment" + ] = proto.RepeatedField( + proto.MESSAGE, + number=5, + message="AnswerQueryRequest.SearchSpec.SearchResultList.SearchResult.UnstructuredDocumentInfo.ExtractiveSegment", + ) + extractive_answers: MutableSequence[ + "AnswerQueryRequest.SearchSpec.SearchResultList.SearchResult.UnstructuredDocumentInfo.ExtractiveAnswer" + ] = proto.RepeatedField( + proto.MESSAGE, + number=6, + message="AnswerQueryRequest.SearchSpec.SearchResultList.SearchResult.UnstructuredDocumentInfo.ExtractiveAnswer", + ) + + class ChunkInfo(proto.Message): + r"""Chunk information. + + Attributes: + chunk (str): + Chunk resource name. + content (str): + Chunk textual content. + """ + + chunk: str = proto.Field( + proto.STRING, + number=1, + ) + content: str = proto.Field( + proto.STRING, + number=2, + ) + + unstructured_document_info: "AnswerQueryRequest.SearchSpec.SearchResultList.SearchResult.UnstructuredDocumentInfo" = proto.Field( + proto.MESSAGE, + number=1, + oneof="content", + message="AnswerQueryRequest.SearchSpec.SearchResultList.SearchResult.UnstructuredDocumentInfo", + ) + chunk_info: "AnswerQueryRequest.SearchSpec.SearchResultList.SearchResult.ChunkInfo" = proto.Field( + proto.MESSAGE, + number=2, + oneof="content", + message="AnswerQueryRequest.SearchSpec.SearchResultList.SearchResult.ChunkInfo", + ) + + search_results: MutableSequence[ + "AnswerQueryRequest.SearchSpec.SearchResultList.SearchResult" + ] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="AnswerQueryRequest.SearchSpec.SearchResultList.SearchResult", + ) + + search_params: "AnswerQueryRequest.SearchSpec.SearchParams" = proto.Field( + proto.MESSAGE, + number=1, + oneof="input", + message="AnswerQueryRequest.SearchSpec.SearchParams", + ) + search_result_list: "AnswerQueryRequest.SearchSpec.SearchResultList" = ( + proto.Field( + proto.MESSAGE, + number=2, + oneof="input", + message="AnswerQueryRequest.SearchSpec.SearchResultList", + ) + ) + + class QueryUnderstandingSpec(proto.Message): + r"""Query understanding specification. + + Attributes: + query_classification_spec (google.cloud.discoveryengine_v1alpha.types.AnswerQueryRequest.QueryUnderstandingSpec.QueryClassificationSpec): + Query classification specification. + query_rephraser_spec (google.cloud.discoveryengine_v1alpha.types.AnswerQueryRequest.QueryUnderstandingSpec.QueryRephraserSpec): + Query rephraser specification. + """ + + class QueryClassificationSpec(proto.Message): + r"""Query classification specification. + + Attributes: + types (MutableSequence[google.cloud.discoveryengine_v1alpha.types.AnswerQueryRequest.QueryUnderstandingSpec.QueryClassificationSpec.Type]): + Enabled query classification types. + """ + + class Type(proto.Enum): + r"""Query classification types. + + Values: + TYPE_UNSPECIFIED (0): + Unspecified query classification type. + ADVERSARIAL_QUERY (1): + Adversarial query classification type. + NON_ANSWER_SEEKING_QUERY (2): + Non-answer-seeking query classification type. + """ + TYPE_UNSPECIFIED = 0 + ADVERSARIAL_QUERY = 1 + NON_ANSWER_SEEKING_QUERY = 2 + + types: MutableSequence[ + "AnswerQueryRequest.QueryUnderstandingSpec.QueryClassificationSpec.Type" + ] = proto.RepeatedField( + proto.ENUM, + number=1, + enum="AnswerQueryRequest.QueryUnderstandingSpec.QueryClassificationSpec.Type", + ) + + class QueryRephraserSpec(proto.Message): + r"""Query rephraser specification. + + Attributes: + disable (bool): + Disable query rephraser. + max_rephrase_steps (int): + Max rephrase steps. + The max number is 10 steps. + If not set or set to < 1, it will be set to 1 by + default. + """ + + disable: bool = proto.Field( + proto.BOOL, + number=1, + ) + max_rephrase_steps: int = proto.Field( + proto.INT32, + number=2, + ) + + query_classification_spec: "AnswerQueryRequest.QueryUnderstandingSpec.QueryClassificationSpec" = proto.Field( + proto.MESSAGE, + number=1, + message="AnswerQueryRequest.QueryUnderstandingSpec.QueryClassificationSpec", + ) + query_rephraser_spec: "AnswerQueryRequest.QueryUnderstandingSpec.QueryRephraserSpec" = proto.Field( + proto.MESSAGE, + number=2, + message="AnswerQueryRequest.QueryUnderstandingSpec.QueryRephraserSpec", + ) + + serving_config: str = proto.Field( + proto.STRING, + number=1, + ) + query: gcd_session.Query = proto.Field( + proto.MESSAGE, + number=2, + message=gcd_session.Query, + ) + session: str = proto.Field( + proto.STRING, + number=3, + ) + safety_spec: SafetySpec = proto.Field( + proto.MESSAGE, + number=4, + message=SafetySpec, + ) + related_questions_spec: RelatedQuestionsSpec = proto.Field( + proto.MESSAGE, + number=5, + message=RelatedQuestionsSpec, + ) + answer_generation_spec: AnswerGenerationSpec = proto.Field( + proto.MESSAGE, + number=7, + message=AnswerGenerationSpec, + ) + search_spec: SearchSpec = proto.Field( + proto.MESSAGE, + number=8, + message=SearchSpec, + ) + query_understanding_spec: QueryUnderstandingSpec = proto.Field( + proto.MESSAGE, + number=9, + message=QueryUnderstandingSpec, + ) + asynchronous_mode: bool = proto.Field( + proto.BOOL, + number=10, + ) + user_pseudo_id: str = proto.Field( + proto.STRING, + number=12, + ) + + +class AnswerQueryResponse(proto.Message): + r"""Response message for + [ConversationalSearchService.AnswerQuery][google.cloud.discoveryengine.v1alpha.ConversationalSearchService.AnswerQuery] + method. + + Attributes: + answer (google.cloud.discoveryengine_v1alpha.types.Answer): + Answer resource object. If + [AnswerQueryRequest.StepSpec.max_step_count][] is greater + than 1, use + [Answer.name][google.cloud.discoveryengine.v1alpha.Answer.name] + to fetch answer information using + [ConversationalSearchService.GetAnswer][google.cloud.discoveryengine.v1alpha.ConversationalSearchService.GetAnswer] + API. + session (google.cloud.discoveryengine_v1alpha.types.Session): + Session resource object. It will be only available when + session field is set and valid in the + [AnswerQueryRequest][google.cloud.discoveryengine.v1alpha.AnswerQueryRequest] + request. + """ + + answer: gcd_answer.Answer = proto.Field( + proto.MESSAGE, + number=1, + message=gcd_answer.Answer, + ) + session: gcd_session.Session = proto.Field( + proto.MESSAGE, + number=2, + message=gcd_session.Session, + ) + + +class GetAnswerRequest(proto.Message): + r"""Request for GetAnswer method. + + Attributes: + name (str): + Required. The resource name of the Answer to get. Format: + ``projects/{project_number}/locations/{location_id}/collections/{collection}/engines/{engine_id}/sessions/{session_id}/answers/{answer_id}`` + """ + + name: str = proto.Field( + proto.STRING, + number=1, + ) + + +class CreateSessionRequest(proto.Message): + r"""Request for CreateSession method. + + Attributes: + parent (str): + Required. Full resource name of parent data store. Format: + ``projects/{project_number}/locations/{location_id}/collections/{collection}/dataStores/{data_store_id}`` + session (google.cloud.discoveryengine_v1alpha.types.Session): + Required. The session to create. + """ + + parent: str = proto.Field( + proto.STRING, + number=1, + ) + session: gcd_session.Session = proto.Field( + proto.MESSAGE, + number=2, + message=gcd_session.Session, + ) + + +class UpdateSessionRequest(proto.Message): + r"""Request for UpdateSession method. + + Attributes: + session (google.cloud.discoveryengine_v1alpha.types.Session): + Required. The Session to update. + update_mask (google.protobuf.field_mask_pb2.FieldMask): + Indicates which fields in the provided + [Session][google.cloud.discoveryengine.v1alpha.Session] to + update. The following are NOT supported: + + - [Session.name][google.cloud.discoveryengine.v1alpha.Session.name] + + If not set or empty, all supported fields are updated. + """ + + session: gcd_session.Session = proto.Field( + proto.MESSAGE, + number=1, + message=gcd_session.Session, + ) + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=2, + message=field_mask_pb2.FieldMask, + ) + + +class DeleteSessionRequest(proto.Message): + r"""Request for DeleteSession method. + + Attributes: + name (str): + Required. The resource name of the Session to delete. + Format: + ``projects/{project_number}/locations/{location_id}/collections/{collection}/dataStores/{data_store_id}/sessions/{session_id}`` + """ + + name: str = proto.Field( + proto.STRING, + number=1, + ) + + +class GetSessionRequest(proto.Message): + r"""Request for GetSession method. + + Attributes: + name (str): + Required. The resource name of the Session to get. Format: + ``projects/{project_number}/locations/{location_id}/collections/{collection}/dataStores/{data_store_id}/sessions/{session_id}`` + """ + + name: str = proto.Field( + proto.STRING, + number=1, + ) + + +class ListSessionsRequest(proto.Message): + r"""Request for ListSessions method. + + Attributes: + parent (str): + Required. The data store resource name. Format: + ``projects/{project_number}/locations/{location_id}/collections/{collection}/dataStores/{data_store_id}`` + page_size (int): + Maximum number of results to return. If + unspecified, defaults to 50. Max allowed value + is 1000. + page_token (str): + A page token, received from a previous ``ListSessions`` + call. Provide this to retrieve the subsequent page. + filter (str): + A filter to apply on the list results. The supported + features are: user_pseudo_id, state. + + Example: "user_pseudo_id = some_id". + order_by (str): + A comma-separated list of fields to order by, sorted in + ascending order. Use "desc" after a field name for + descending. Supported fields: + + - ``update_time`` + - ``create_time`` + - ``session_name`` + + Example: "update_time desc" "create_time". + """ + + parent: str = proto.Field( + proto.STRING, + number=1, + ) + page_size: int = proto.Field( + proto.INT32, + number=2, + ) + page_token: str = proto.Field( + proto.STRING, + number=3, + ) + filter: str = proto.Field( + proto.STRING, + number=4, + ) + order_by: str = proto.Field( + proto.STRING, + number=5, + ) + + +class ListSessionsResponse(proto.Message): + r"""Response for ListSessions method. + + Attributes: + sessions (MutableSequence[google.cloud.discoveryengine_v1alpha.types.Session]): + All the Sessions for a given data store. + next_page_token (str): + Pagination token, if not returned indicates + the last page. + """ + + @property + def raw_page(self): + return self + + sessions: MutableSequence[gcd_session.Session] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message=gcd_session.Session, + ) + next_page_token: str = proto.Field( + proto.STRING, + number=2, + ) + + __all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/document.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/document.py index 36f8cc395f55..0134792178ce 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/document.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/document.py @@ -27,6 +27,7 @@ package="google.cloud.discoveryengine.v1alpha", manifest={ "Document", + "ProcessedDocument", }, ) @@ -253,4 +254,34 @@ class AccessRestriction(proto.Message): ) +class ProcessedDocument(proto.Message): + r"""Document captures all raw metadata information of items to be + recommended or searched. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + json_data (str): + The JSON string representation of the + processed document. + + This field is a member of `oneof`_ ``processed_data_format``. + document (str): + Required. Full resource name of the referenced document, in + the format + ``projects/*/locations/*/collections/*/dataStores/*/branches/*/documents/*``. + """ + + json_data: str = proto.Field( + proto.STRING, + number=2, + oneof="processed_data_format", + ) + document: str = proto.Field( + proto.STRING, + number=1, + ) + + __all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/document_processing_config.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/document_processing_config.py index fc568da34fdf..11db01fea067 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/document_processing_config.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/document_processing_config.py @@ -142,12 +142,9 @@ class OcrParsingConfig(proto.Message): Attributes: enhanced_document_elements (MutableSequence[str]): - Apply additional enhanced OCR processing to a list of - document elements. - - Supported values: - - - ``table``: advanced table parsing model. + [DEPRECATED] This field is deprecated. To use the additional + enhanced document elements processing, please switch to + ``layout_parsing_config``. use_native_text (bool): If true, will use native text instead of OCR text on pages containing native text. diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/document_service.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/document_service.py index c01f4e45e1a8..b4cae08db273 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/document_service.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/document_service.py @@ -31,6 +31,7 @@ "CreateDocumentRequest", "UpdateDocumentRequest", "DeleteDocumentRequest", + "GetProcessedDocumentRequest", }, ) @@ -272,4 +273,77 @@ class DeleteDocumentRequest(proto.Message): ) +class GetProcessedDocumentRequest(proto.Message): + r"""Request message for + [DocumentService.GetDocument][google.cloud.discoveryengine.v1alpha.DocumentService.GetDocument] + method. + + Attributes: + name (str): + Required. Full resource name of + [Document][google.cloud.discoveryengine.v1alpha.Document], + such as + ``projects/{project}/locations/{location}/collections/{collection}/dataStores/{data_store}/branches/{branch}/documents/{document}``. + + If the caller does not have permission to access the + [Document][google.cloud.discoveryengine.v1alpha.Document], + regardless of whether or not it exists, a + ``PERMISSION_DENIED`` error is returned. + + If the requested + [Document][google.cloud.discoveryengine.v1alpha.Document] + does not exist, a ``NOT_FOUND`` error is returned. + processed_document_type (google.cloud.discoveryengine_v1alpha.types.GetProcessedDocumentRequest.ProcessedDocumentType): + Required. What type of processing to return. + processed_document_format (google.cloud.discoveryengine_v1alpha.types.GetProcessedDocumentRequest.ProcessedDocumentFormat): + What format output should be. If + unspecified, defaults to JSON. + """ + + class ProcessedDocumentType(proto.Enum): + r"""The type of processing to return in the response. + + Values: + PROCESSED_DOCUMENT_TYPE_UNSPECIFIED (0): + Default value. + PARSED_DOCUMENT (1): + Available for all data store parsing configs. + CHUNKED_DOCUMENT (2): + Only available if ChunkingConfig is enabeld + on the data store. + """ + PROCESSED_DOCUMENT_TYPE_UNSPECIFIED = 0 + PARSED_DOCUMENT = 1 + CHUNKED_DOCUMENT = 2 + + class ProcessedDocumentFormat(proto.Enum): + r"""The format of the returned processed document. If + unspecified, defaults to JSON. + + Values: + PROCESSED_DOCUMENT_FORMAT_UNSPECIFIED (0): + Default value. + JSON (1): + output format will be a JSON string + representation of processed document. + """ + PROCESSED_DOCUMENT_FORMAT_UNSPECIFIED = 0 + JSON = 1 + + name: str = proto.Field( + proto.STRING, + number=1, + ) + processed_document_type: ProcessedDocumentType = proto.Field( + proto.ENUM, + number=2, + enum=ProcessedDocumentType, + ) + processed_document_format: ProcessedDocumentFormat = proto.Field( + proto.ENUM, + number=3, + enum=ProcessedDocumentFormat, + ) + + __all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/engine.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/engine.py index cac49806de86..1d7bab010360 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/engine.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/engine.py @@ -153,7 +153,7 @@ class SearchEngineConfig(proto.Message): The search feature tier of this engine. Different tiers might have different pricing. To learn more, - please check the pricing documentation. + check the pricing documentation. Defaults to [SearchTier.SEARCH_TIER_STANDARD][google.cloud.discoveryengine.v1alpha.SearchTier.SEARCH_TIER_STANDARD] @@ -315,7 +315,7 @@ class ChatEngineConfig(proto.Message): [EngineService.GetEngine][google.cloud.discoveryengine.v1alpha.EngineService.GetEngine] or [EngineService.ListEngines][google.cloud.discoveryengine.v1alpha.EngineService.ListEngines] - API after engine creation. Please use + API after engine creation. Use [ChatEngineMetadata.dialogflow_agent][google.cloud.discoveryengine.v1alpha.Engine.ChatEngineMetadata.dialogflow_agent] for actual agent association after Engine is created. """ diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/grounded_generation_service.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/grounded_generation_service.py new file mode 100644 index 000000000000..667ae4abb0ed --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/grounded_generation_service.py @@ -0,0 +1,186 @@ +# -*- 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 + +from google.cloud.discoveryengine_v1alpha.types import grounding + +__protobuf__ = proto.module( + package="google.cloud.discoveryengine.v1alpha", + manifest={ + "CheckGroundingSpec", + "CheckGroundingRequest", + "CheckGroundingResponse", + }, +) + + +class CheckGroundingSpec(proto.Message): + r"""Specification for the grounding check. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + citation_threshold (float): + The threshold (in [0,1]) used for determining whether a fact + must be cited for a claim in the answer candidate. Choosing + a higher threshold will lead to fewer but very strong + citations, while choosing a lower threshold may lead to more + but somewhat weaker citations. If unset, the threshold will + default to 0.6. + + This field is a member of `oneof`_ ``_citation_threshold``. + """ + + citation_threshold: float = proto.Field( + proto.DOUBLE, + number=1, + optional=True, + ) + + +class CheckGroundingRequest(proto.Message): + r"""Request message for + [GroundedGenerationService.CheckGrounding][google.cloud.discoveryengine.v1alpha.GroundedGenerationService.CheckGrounding] + method. + + Attributes: + grounding_config (str): + Required. The resource name of the grounding config, such as + ``projects/*/locations/global/groundingConfigs/default_grounding_config``. + answer_candidate (str): + Answer candidate to check. + facts (MutableSequence[google.cloud.discoveryengine_v1alpha.types.GroundingFact]): + List of facts for the grounding check. + We support up to 200 facts. + grounding_spec (google.cloud.discoveryengine_v1alpha.types.CheckGroundingSpec): + Configuration of the grounding check. + """ + + grounding_config: str = proto.Field( + proto.STRING, + number=1, + ) + answer_candidate: str = proto.Field( + proto.STRING, + number=2, + ) + facts: MutableSequence[grounding.GroundingFact] = proto.RepeatedField( + proto.MESSAGE, + number=3, + message=grounding.GroundingFact, + ) + grounding_spec: "CheckGroundingSpec" = proto.Field( + proto.MESSAGE, + number=4, + message="CheckGroundingSpec", + ) + + +class CheckGroundingResponse(proto.Message): + r"""Response message for the + [GroundedGenerationService.CheckGrounding][google.cloud.discoveryengine.v1alpha.GroundedGenerationService.CheckGrounding] + method. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + support_score (float): + The support score for the input answer + candidate. Higher the score, higher is the + fraction of claims that are supported by the + provided facts. This is always set when a + response is returned. + + This field is a member of `oneof`_ ``_support_score``. + cited_chunks (MutableSequence[google.cloud.discoveryengine_v1alpha.types.FactChunk]): + List of facts cited across all claims in the + answer candidate. These are derived from the + facts supplied in the request. + claims (MutableSequence[google.cloud.discoveryengine_v1alpha.types.CheckGroundingResponse.Claim]): + Claim texts and citation info across all + claims in the answer candidate. + """ + + class Claim(proto.Message): + r"""Text and citation info for a claim in the answer candidate. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + start_pos (int): + Position indicating the start of the claim in + the answer candidate, measured in bytes. + + This field is a member of `oneof`_ ``_start_pos``. + end_pos (int): + Position indicating the end of the claim in + the answer candidate, exclusive. + + This field is a member of `oneof`_ ``_end_pos``. + claim_text (str): + Text for the claim in the answer candidate. + Always provided regardless of whether citations + or anti-citations are found. + citation_indices (MutableSequence[int]): + A list of indices (into 'cited_chunks') specifying the + citations associated with the claim. For instance [1,3,4] + means that cited_chunks[1], cited_chunks[3], cited_chunks[4] + are the facts cited supporting for the claim. A citation to + a fact indicates that the claim is supported by the fact. + """ + + start_pos: int = proto.Field( + proto.INT32, + number=1, + optional=True, + ) + end_pos: int = proto.Field( + proto.INT32, + number=2, + optional=True, + ) + claim_text: str = proto.Field( + proto.STRING, + number=3, + ) + citation_indices: MutableSequence[int] = proto.RepeatedField( + proto.INT32, + number=4, + ) + + support_score: float = proto.Field( + proto.FLOAT, + number=1, + optional=True, + ) + cited_chunks: MutableSequence[grounding.FactChunk] = proto.RepeatedField( + proto.MESSAGE, + number=3, + message=grounding.FactChunk, + ) + claims: MutableSequence[Claim] = proto.RepeatedField( + proto.MESSAGE, + number=4, + message=Claim, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/grounding.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/grounding.py new file mode 100644 index 000000000000..cf1775b6f6ee --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/grounding.py @@ -0,0 +1,89 @@ +# -*- 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.discoveryengine.v1alpha", + manifest={ + "GroundingFact", + "FactChunk", + }, +) + + +class GroundingFact(proto.Message): + r"""Grounding Fact. + + Attributes: + fact_text (str): + Text content of the fact. Can be at most 10K + characters long. + attributes (MutableMapping[str, str]): + Attributes associated with the fact. Common attributes + include ``source`` (indicating where the fact was sourced + from), ``author`` (indicating the author of the fact), and + so on. + """ + + fact_text: str = proto.Field( + proto.STRING, + number=1, + ) + attributes: MutableMapping[str, str] = proto.MapField( + proto.STRING, + proto.STRING, + number=2, + ) + + +class FactChunk(proto.Message): + r"""Fact Chunk. + + Attributes: + chunk_text (str): + Text content of the fact chunk. Can be at + most 10K characters long. + source (str): + Source from which this fact chunk was + retrieved. If it was retrieved from the + GroundingFacts provided in the request then this + field will contain the index of the specific + fact from which this chunk was retrieved. + source_metadata (MutableMapping[str, str]): + More fine-grained information for the source + reference. + """ + + chunk_text: str = proto.Field( + proto.STRING, + number=1, + ) + source: str = proto.Field( + proto.STRING, + number=2, + ) + source_metadata: MutableMapping[str, str] = proto.MapField( + proto.STRING, + proto.STRING, + number=3, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/import_config.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/import_config.py index 268492cc53b0..b45cb43efa98 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/import_config.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/import_config.py @@ -17,6 +17,7 @@ from typing import MutableMapping, MutableSequence +from google.protobuf import field_mask_pb2 # type: ignore from google.protobuf import timestamp_pb2 # type: ignore from google.rpc import status_pb2 # type: ignore from google.type import date_pb2 # type: ignore @@ -29,6 +30,12 @@ manifest={ "GcsSource", "BigQuerySource", + "SpannerSource", + "BigtableOptions", + "BigtableSource", + "FhirStoreSource", + "CloudSqlSource", + "FirestoreSource", "ImportErrorConfig", "ImportUserEventsRequest", "ImportUserEventsResponse", @@ -73,11 +80,13 @@ class GcsSource(proto.Message): - ``custom``: One custom data JSON per row in arbitrary format that conforms to the defined [Schema][google.cloud.discoveryengine.v1alpha.Schema] of - the data store. This can only be used by Gen App Builder. + the data store. This can only be used by the GENERIC Data + Store vertical. - ``csv``: A CSV file with header conforming to the defined [Schema][google.cloud.discoveryengine.v1alpha.Schema] of the data store. Each entry after the header is imported - as a Document. This can only be used by Gen App Builder. + as a Document. This can only be used by the GENERIC Data + Store vertical. Supported values for user even imports: @@ -147,7 +156,8 @@ class BigQuerySource(proto.Message): - ``custom``: One custom data per row in arbitrary format that conforms to the defined [Schema][google.cloud.discoveryengine.v1alpha.Schema] of - the data store. This can only be used by Gen App Builder. + the data store. This can only be used by the GENERIC Data + Store vertical. """ partition_date: date_pb2.Date = proto.Field( @@ -178,6 +188,402 @@ class BigQuerySource(proto.Message): ) +class SpannerSource(proto.Message): + r"""The Spanner source for importing data + + Attributes: + project_id (str): + The project ID that the Spanner source is in + with a length limit of 128 characters. If not + specified, inherits the project ID from the + parent request. + instance_id (str): + Required. The instance ID of the source + Spanner table. + database_id (str): + Required. The database ID of the source + Spanner table. + table_id (str): + Required. The table name of the Spanner + database that needs to be imported. + enable_data_boost (bool): + Whether to apply data boost on Spanner export. Enabling this + option will incur additional cost. More info can be found + `here `__. + """ + + project_id: str = proto.Field( + proto.STRING, + number=1, + ) + instance_id: str = proto.Field( + proto.STRING, + number=2, + ) + database_id: str = proto.Field( + proto.STRING, + number=3, + ) + table_id: str = proto.Field( + proto.STRING, + number=4, + ) + enable_data_boost: bool = proto.Field( + proto.BOOL, + number=5, + ) + + +class BigtableOptions(proto.Message): + r"""The Bigtable Options object that contains information to + support the import. + + Attributes: + key_field_name (str): + The field name used for saving row key value in the + document. The name has to match the pattern + ``[a-zA-Z0-9][a-zA-Z0-9-_]*``. + families (MutableMapping[str, google.cloud.discoveryengine_v1alpha.types.BigtableOptions.BigtableColumnFamily]): + The mapping from family names to an object + that contains column families level information + for the given column family. If a family is not + present in this map it will be ignored. + """ + + class Type(proto.Enum): + r"""The type of values in a Bigtable column or column family. The values + are expected to be encoded using `HBase + Bytes.toBytes `__ + function when the encoding value is set to ``BINARY``. + + Values: + TYPE_UNSPECIFIED (0): + The type is unspecified. + STRING (1): + String type. + NUMBER (2): + Numerical type. + INTEGER (3): + Integer type. + VAR_INTEGER (4): + Variable length integer type. + BIG_NUMERIC (5): + BigDecimal type. + BOOLEAN (6): + Boolean type. + JSON (7): + JSON type. + """ + TYPE_UNSPECIFIED = 0 + STRING = 1 + NUMBER = 2 + INTEGER = 3 + VAR_INTEGER = 4 + BIG_NUMERIC = 5 + BOOLEAN = 6 + JSON = 7 + + class Encoding(proto.Enum): + r"""The encoding mode of a Bigtable column or column family. + + Values: + ENCODING_UNSPECIFIED (0): + The encoding is unspecified. + TEXT (1): + Text encoding. + BINARY (2): + Binary encoding. + """ + ENCODING_UNSPECIFIED = 0 + TEXT = 1 + BINARY = 2 + + class BigtableColumnFamily(proto.Message): + r"""The column family of the Bigtable. + + Attributes: + field_name (str): + The field name to use for this column family in the + document. The name has to match the pattern + ``[a-zA-Z0-9][a-zA-Z0-9-_]*``. If not set, it is parsed from + the family name with best effort. However, due to different + naming patterns, field name collisions could happen, where + parsing behavior is undefined. + encoding (google.cloud.discoveryengine_v1alpha.types.BigtableOptions.Encoding): + The encoding mode of the values when the type is not STRING. + Acceptable encoding values are: + + - ``TEXT``: indicates values are alphanumeric text strings. + - ``BINARY``: indicates values are encoded using + ``HBase Bytes.toBytes`` family of functions. This can be + overridden for a specific column by listing that column + in ``columns`` and specifying an encoding for it. + type_ (google.cloud.discoveryengine_v1alpha.types.BigtableOptions.Type): + The type of values in this column family. The values are + expected to be encoded using ``HBase Bytes.toBytes`` + function when the encoding value is set to ``BINARY``. + columns (MutableSequence[google.cloud.discoveryengine_v1alpha.types.BigtableOptions.BigtableColumn]): + The list of objects that contains column + level information for each column. If a column + is not present in this list it will be ignored. + """ + + field_name: str = proto.Field( + proto.STRING, + number=1, + ) + encoding: "BigtableOptions.Encoding" = proto.Field( + proto.ENUM, + number=2, + enum="BigtableOptions.Encoding", + ) + type_: "BigtableOptions.Type" = proto.Field( + proto.ENUM, + number=3, + enum="BigtableOptions.Type", + ) + columns: MutableSequence[ + "BigtableOptions.BigtableColumn" + ] = proto.RepeatedField( + proto.MESSAGE, + number=4, + message="BigtableOptions.BigtableColumn", + ) + + class BigtableColumn(proto.Message): + r"""The column of the Bigtable. + + Attributes: + qualifier (bytes): + Required. Qualifier of the column. If it + cannot be decoded with utf-8, use a base-64 + encoded string instead. + field_name (str): + The field name to use for this column in the document. The + name has to match the pattern ``[a-zA-Z0-9][a-zA-Z0-9-_]*``. + If not set, it is parsed from the qualifier bytes with best + effort. However, due to different naming patterns, field + name collisions could happen, where parsing behavior is + undefined. + encoding (google.cloud.discoveryengine_v1alpha.types.BigtableOptions.Encoding): + The encoding mode of the values when the type is not + ``STRING``. Acceptable encoding values are: + + - ``TEXT``: indicates values are alphanumeric text strings. + - ``BINARY``: indicates values are encoded using + ``HBase Bytes.toBytes`` family of functions. This can be + overridden for a specific column by listing that column + in ``columns`` and specifying an encoding for it. + type_ (google.cloud.discoveryengine_v1alpha.types.BigtableOptions.Type): + The type of values in this column family. The values are + expected to be encoded using ``HBase Bytes.toBytes`` + function when the encoding value is set to ``BINARY``. + """ + + qualifier: bytes = proto.Field( + proto.BYTES, + number=1, + ) + field_name: str = proto.Field( + proto.STRING, + number=2, + ) + encoding: "BigtableOptions.Encoding" = proto.Field( + proto.ENUM, + number=3, + enum="BigtableOptions.Encoding", + ) + type_: "BigtableOptions.Type" = proto.Field( + proto.ENUM, + number=4, + enum="BigtableOptions.Type", + ) + + key_field_name: str = proto.Field( + proto.STRING, + number=1, + ) + families: MutableMapping[str, BigtableColumnFamily] = proto.MapField( + proto.STRING, + proto.MESSAGE, + number=2, + message=BigtableColumnFamily, + ) + + +class BigtableSource(proto.Message): + r"""The Cloud Bigtable source for importing data. + + Attributes: + project_id (str): + The project ID that the Bigtable source is in + with a length limit of 128 characters. If not + specified, inherits the project ID from the + parent request. + instance_id (str): + Required. The instance ID of the Cloud + Bigtable that needs to be imported. + table_id (str): + Required. The table ID of the Cloud Bigtable + that needs to be imported. + bigtable_options (google.cloud.discoveryengine_v1alpha.types.BigtableOptions): + Required. Bigtable options that contains + information needed when parsing data into typed + structures. For example, column type + annotations. + """ + + project_id: str = proto.Field( + proto.STRING, + number=1, + ) + instance_id: str = proto.Field( + proto.STRING, + number=2, + ) + table_id: str = proto.Field( + proto.STRING, + number=3, + ) + bigtable_options: "BigtableOptions" = proto.Field( + proto.MESSAGE, + number=4, + message="BigtableOptions", + ) + + +class FhirStoreSource(proto.Message): + r"""Cloud FhirStore source import data from. + + Attributes: + fhir_store (str): + Required. The full resource name of the FHIR store to import + data from, in the format of + ``projects/{project}/locations/{location}/datasets/{dataset}/fhirStores/{fhir_store}``. + gcs_staging_dir (str): + Intermediate Cloud Storage directory used for + the import with a length limit of 2,000 + characters. Can be specified if one wants to + have the FhirStore export to a specific Cloud + Storage directory. + """ + + fhir_store: str = proto.Field( + proto.STRING, + number=1, + ) + gcs_staging_dir: str = proto.Field( + proto.STRING, + number=2, + ) + + +class CloudSqlSource(proto.Message): + r"""Cloud SQL source import data from. + + Attributes: + project_id (str): + The project ID that the Cloud SQL source is + in with a length limit of 128 characters. If not + specified, inherits the project ID from the + parent request. + instance_id (str): + Required. The Cloud SQL instance to copy the + data from with a length limit of 256 characters. + database_id (str): + Required. The Cloud SQL database to copy the + data from with a length limit of 256 characters. + table_id (str): + Required. The Cloud SQL table to copy the + data from with a length limit of 256 characters. + gcs_staging_dir (str): + Intermediate Cloud Storage directory used for + the import with a length limit of 2,000 + characters. Can be specified if one wants to + have the Cloud SQL export to a specific Cloud + Storage directory. + + Ensure that the Cloud SQL service account has + the necessary Cloud Storage Admin permissions to + access the specified Cloud Storage directory. + offload (bool): + Option for serverless export. Enabling this option will + incur additional cost. More info can be found + `here `__. + """ + + project_id: str = proto.Field( + proto.STRING, + number=1, + ) + instance_id: str = proto.Field( + proto.STRING, + number=2, + ) + database_id: str = proto.Field( + proto.STRING, + number=3, + ) + table_id: str = proto.Field( + proto.STRING, + number=4, + ) + gcs_staging_dir: str = proto.Field( + proto.STRING, + number=5, + ) + offload: bool = proto.Field( + proto.BOOL, + number=6, + ) + + +class FirestoreSource(proto.Message): + r"""Firestore source import data from. + + Attributes: + project_id (str): + The project ID that the Cloud SQL source is + in with a length limit of 128 characters. If not + specified, inherits the project ID from the + parent request. + database_id (str): + Required. The Firestore database to copy the + data from with a length limit of 256 characters. + collection_id (str): + Required. The Firestore collection to copy + the data from with a length limit of 1,500 + characters. + gcs_staging_dir (str): + Intermediate Cloud Storage directory used for + the import with a length limit of 2,000 + characters. Can be specified if one wants to + have the Firestore export to a specific Cloud + Storage directory. + + Ensure that the Firestore service account has + the necessary Cloud Storage Admin permissions to + access the specified Cloud Storage directory. + """ + + project_id: str = proto.Field( + proto.STRING, + number=1, + ) + database_id: str = proto.Field( + proto.STRING, + number=2, + ) + collection_id: str = proto.Field( + proto.STRING, + number=3, + ) + gcs_staging_dir: str = proto.Field( + proto.STRING, + number=4, + ) + + class ImportErrorConfig(proto.Message): r"""Configuration of destination for Import related errors. @@ -376,6 +782,8 @@ class ImportDocumentsMetadata(proto.Message): failure_count (int): Count of entries that encountered errors while processing. + total_count (int): + Total count of entries that were processed. """ create_time: timestamp_pb2.Timestamp = proto.Field( @@ -396,6 +804,10 @@ class ImportDocumentsMetadata(proto.Message): proto.INT64, number=4, ) + total_count: int = proto.Field( + proto.INT64, + number=5, + ) class ImportDocumentsRequest(proto.Message): @@ -421,6 +833,26 @@ class ImportDocumentsRequest(proto.Message): bigquery_source (google.cloud.discoveryengine_v1alpha.types.BigQuerySource): BigQuery input source. + This field is a member of `oneof`_ ``source``. + fhir_store_source (google.cloud.discoveryengine_v1alpha.types.FhirStoreSource): + FhirStore input source. + + This field is a member of `oneof`_ ``source``. + spanner_source (google.cloud.discoveryengine_v1alpha.types.SpannerSource): + Spanner input source. + + This field is a member of `oneof`_ ``source``. + cloud_sql_source (google.cloud.discoveryengine_v1alpha.types.CloudSqlSource): + Cloud SQL input source. + + This field is a member of `oneof`_ ``source``. + firestore_source (google.cloud.discoveryengine_v1alpha.types.FirestoreSource): + Firestore input source. + + This field is a member of `oneof`_ ``source``. + bigtable_source (google.cloud.discoveryengine_v1alpha.types.BigtableSource): + Cloud Bigtable input source. + This field is a member of `oneof`_ ``source``. parent (str): Required. The parent branch resource name, such as @@ -433,6 +865,10 @@ class ImportDocumentsRequest(proto.Message): The mode of reconciliation between existing documents and the documents to be imported. Defaults to [ReconciliationMode.INCREMENTAL][google.cloud.discoveryengine.v1alpha.ImportDocumentsRequest.ReconciliationMode.INCREMENTAL]. + update_mask (google.protobuf.field_mask_pb2.FieldMask): + Indicates which fields in the provided + imported documents to update. If not set, the + default is to update all fields. auto_generate_ids (bool): Whether to automatically generate IDs for the documents if absent. @@ -450,52 +886,61 @@ class ImportDocumentsRequest(proto.Message): [id_field][google.cloud.discoveryengine.v1alpha.ImportDocumentsRequest.id_field], otherwise, documents without IDs fail to be imported. - Only set this field when using - [GcsSource][google.cloud.discoveryengine.v1alpha.GcsSource] - or - [BigQuerySource][google.cloud.discoveryengine.v1alpha.BigQuerySource], - and when - [GcsSource.data_schema][google.cloud.discoveryengine.v1alpha.GcsSource.data_schema] - or - [BigQuerySource.data_schema][google.cloud.discoveryengine.v1alpha.BigQuerySource.data_schema] - is ``custom`` or ``csv``. Otherwise, an INVALID_ARGUMENT - error is thrown. + Supported data sources: + + - [GcsSource][google.cloud.discoveryengine.v1alpha.GcsSource]. + [GcsSource.data_schema][google.cloud.discoveryengine.v1alpha.GcsSource.data_schema] + must be ``custom`` or ``csv``. Otherwise, an + INVALID_ARGUMENT error is thrown. + - [BigQuerySource][google.cloud.discoveryengine.v1alpha.BigQuerySource]. + [BigQuerySource.data_schema][google.cloud.discoveryengine.v1alpha.BigQuerySource.data_schema] + must be ``custom`` or ``csv``. Otherwise, an + INVALID_ARGUMENT error is thrown. + - [SpannerSource][google.cloud.discoveryengine.v1alpha.SpannerSource]. + - [CloudSqlSource][google.cloud.discoveryengine.v1alpha.CloudSqlSource]. + - [FirestoreSource][google.cloud.discoveryengine.v1alpha.FirestoreSource]. + - [BigtableSource][google.cloud.discoveryengine.v1alpha.BigtableSource]. id_field (str): - The field in the Cloud Storage and BigQuery sources that - indicates the unique IDs of the documents. + The field indicates the ID field or column to be used as + unique IDs of the documents. For [GcsSource][google.cloud.discoveryengine.v1alpha.GcsSource] it is the key of the JSON field. For instance, ``my_id`` for - JSON ``{"my_id": "some_uuid"}``. For - [BigQuerySource][google.cloud.discoveryengine.v1alpha.BigQuerySource] - it is the column name of the BigQuery table where the unique - ids are stored. + JSON ``{"my_id": "some_uuid"}``. For others, it may be the + column name of the table where the unique ids are stored. - The values of the JSON field or the BigQuery column are used - as the + The values of the JSON field or the table column are used as + the [Document.id][google.cloud.discoveryengine.v1alpha.Document.id]s. - The JSON field or the BigQuery column must be of string - type, and the values must be set as valid strings conform to + The JSON field or the table column must be of string type, + and the values must be set as valid strings conform to `RFC-1034 `__ with 1-63 characters. Otherwise, documents without valid IDs fail to be imported. - Only set this field when using - [GcsSource][google.cloud.discoveryengine.v1alpha.GcsSource] - or - [BigQuerySource][google.cloud.discoveryengine.v1alpha.BigQuerySource], - and when - [GcsSource.data_schema][google.cloud.discoveryengine.v1alpha.GcsSource.data_schema] - or - [BigQuerySource.data_schema][google.cloud.discoveryengine.v1alpha.BigQuerySource.data_schema] - is ``custom``. And only set this field when + Only set this field when [auto_generate_ids][google.cloud.discoveryengine.v1alpha.ImportDocumentsRequest.auto_generate_ids] is unset or set as ``false``. Otherwise, an INVALID_ARGUMENT error is thrown. If it is unset, a default value ``_id`` is used when importing from the allowed data sources. + + Supported data sources: + + - [GcsSource][google.cloud.discoveryengine.v1alpha.GcsSource]. + [GcsSource.data_schema][google.cloud.discoveryengine.v1alpha.GcsSource.data_schema] + must be ``custom`` or ``csv``. Otherwise, an + INVALID_ARGUMENT error is thrown. + - [BigQuerySource][google.cloud.discoveryengine.v1alpha.BigQuerySource]. + [BigQuerySource.data_schema][google.cloud.discoveryengine.v1alpha.BigQuerySource.data_schema] + must be ``custom`` or ``csv``. Otherwise, an + INVALID_ARGUMENT error is thrown. + - [SpannerSource][google.cloud.discoveryengine.v1alpha.SpannerSource]. + - [CloudSqlSource][google.cloud.discoveryengine.v1alpha.CloudSqlSource]. + - [FirestoreSource][google.cloud.discoveryengine.v1alpha.FirestoreSource]. + - [BigtableSource][google.cloud.discoveryengine.v1alpha.BigtableSource]. """ class ReconciliationMode(proto.Enum): @@ -554,6 +999,36 @@ class InlineSource(proto.Message): oneof="source", message="BigQuerySource", ) + fhir_store_source: "FhirStoreSource" = proto.Field( + proto.MESSAGE, + number=10, + oneof="source", + message="FhirStoreSource", + ) + spanner_source: "SpannerSource" = proto.Field( + proto.MESSAGE, + number=11, + oneof="source", + message="SpannerSource", + ) + cloud_sql_source: "CloudSqlSource" = proto.Field( + proto.MESSAGE, + number=12, + oneof="source", + message="CloudSqlSource", + ) + firestore_source: "FirestoreSource" = proto.Field( + proto.MESSAGE, + number=13, + oneof="source", + message="FirestoreSource", + ) + bigtable_source: "BigtableSource" = proto.Field( + proto.MESSAGE, + number=15, + oneof="source", + message="BigtableSource", + ) parent: str = proto.Field( proto.STRING, number=1, @@ -568,6 +1043,11 @@ class InlineSource(proto.Message): number=6, enum=ReconciliationMode, ) + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=7, + message=field_mask_pb2.FieldMask, + ) auto_generate_ids: bool = proto.Field( proto.BOOL, number=8, diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/project.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/project.py new file mode 100644 index 000000000000..4762163ef2cd --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/project.py @@ -0,0 +1,152 @@ +# -*- 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 timestamp_pb2 # type: ignore +import proto # type: ignore + +__protobuf__ = proto.module( + package="google.cloud.discoveryengine.v1alpha", + manifest={ + "Project", + }, +) + + +class Project(proto.Message): + r"""Metadata and configurations for a Google Cloud project in the + service. + + Attributes: + name (str): + Output only. Full resource name of the project, for example + ``projects/{project_number}``. Note that when making + requests, project number and project id are both acceptable, + but the server will always respond in project number. + create_time (google.protobuf.timestamp_pb2.Timestamp): + Output only. The timestamp when this project + is created. + provision_completion_time (google.protobuf.timestamp_pb2.Timestamp): + Output only. The timestamp when this project + is successfully provisioned. Empty value means + this project is still provisioning and is not + ready for use. + service_terms_map (MutableMapping[str, google.cloud.discoveryengine_v1alpha.types.Project.ServiceTerms]): + Output only. A map of terms of services. The key is the + ``id`` of + [ServiceTerms][google.cloud.discoveryengine.v1alpha.Project.ServiceTerms]. + """ + + class ServiceTerms(proto.Message): + r"""Metadata about the terms of service. + + Attributes: + id (str): + The unique identifier of this terms of service. Available + terms: + + - ``GA_DATA_USE_TERMS``: `Terms for data + use `__. + When using this as ``id``, the acceptable + [version][google.cloud.discoveryengine.v1alpha.Project.ServiceTerms.version] + to provide is ``2022-11-23``. + version (str): + The version string of the terms of service. For acceptable + values, see the comments for + [id][google.cloud.discoveryengine.v1alpha.Project.ServiceTerms.id] + above. + state (google.cloud.discoveryengine_v1alpha.types.Project.ServiceTerms.State): + Whether the project has accepted/rejected the + service terms or it is still pending. + accept_time (google.protobuf.timestamp_pb2.Timestamp): + The last time when the project agreed to the + terms of service. + decline_time (google.protobuf.timestamp_pb2.Timestamp): + The last time when the project declined or + revoked the agreement to terms of service. + """ + + class State(proto.Enum): + r"""The agreement states this terms of service. + + Values: + STATE_UNSPECIFIED (0): + The default value of the enum. This value is + not actually used. + TERMS_ACCEPTED (1): + The project has given consent to the terms of + service. + TERMS_PENDING (2): + The project is pending to review and accept + the terms of service. + TERMS_DECLINED (3): + The project has declined or revoked the + agreement to terms of service. + """ + STATE_UNSPECIFIED = 0 + TERMS_ACCEPTED = 1 + TERMS_PENDING = 2 + TERMS_DECLINED = 3 + + id: str = proto.Field( + proto.STRING, + number=1, + ) + version: str = proto.Field( + proto.STRING, + number=2, + ) + state: "Project.ServiceTerms.State" = proto.Field( + proto.ENUM, + number=4, + enum="Project.ServiceTerms.State", + ) + accept_time: timestamp_pb2.Timestamp = proto.Field( + proto.MESSAGE, + number=5, + message=timestamp_pb2.Timestamp, + ) + decline_time: timestamp_pb2.Timestamp = proto.Field( + proto.MESSAGE, + number=6, + message=timestamp_pb2.Timestamp, + ) + + name: str = proto.Field( + proto.STRING, + number=1, + ) + create_time: timestamp_pb2.Timestamp = proto.Field( + proto.MESSAGE, + number=2, + message=timestamp_pb2.Timestamp, + ) + provision_completion_time: timestamp_pb2.Timestamp = proto.Field( + proto.MESSAGE, + number=3, + message=timestamp_pb2.Timestamp, + ) + service_terms_map: MutableMapping[str, ServiceTerms] = proto.MapField( + proto.STRING, + proto.MESSAGE, + number=4, + message=ServiceTerms, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/project_service.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/project_service.py new file mode 100644 index 000000000000..fd33292e8422 --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/project_service.py @@ -0,0 +1,152 @@ +# -*- 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.discoveryengine.v1alpha", + manifest={ + "GetProjectRequest", + "ProvisionProjectRequest", + "ProvisionProjectMetadata", + "ReportConsentChangeRequest", + }, +) + + +class GetProjectRequest(proto.Message): + r"""Request message for + [ProjectService.GetProject][google.cloud.discoveryengine.v1alpha.ProjectService.GetProject] + method. + + Attributes: + name (str): + Required. Full resource name of a + [Project][google.cloud.discoveryengine.v1alpha.Project], + such as ``projects/{project_id_or_number}``. + """ + + name: str = proto.Field( + proto.STRING, + number=1, + ) + + +class ProvisionProjectRequest(proto.Message): + r"""Request for + [ProjectService.ProvisionProject][google.cloud.discoveryengine.v1alpha.ProjectService.ProvisionProject] + method. + + Attributes: + name (str): + Required. Full resource name of a + [Project][google.cloud.discoveryengine.v1alpha.Project], + such as ``projects/{project_id_or_number}``. + accept_data_use_terms (bool): + Required. Set to ``true`` to specify that caller has read + and would like to give consent to the `Terms for data + use `__. + data_use_terms_version (str): + Required. The version of the `Terms for data + use `__ that + caller has read and would like to give consent to. + + Acceptable version is ``2022-11-23``, and this may change + over time. + """ + + name: str = proto.Field( + proto.STRING, + number=1, + ) + accept_data_use_terms: bool = proto.Field( + proto.BOOL, + number=2, + ) + data_use_terms_version: str = proto.Field( + proto.STRING, + number=3, + ) + + +class ProvisionProjectMetadata(proto.Message): + r"""Metadata associated with a project provision operation.""" + + +class ReportConsentChangeRequest(proto.Message): + r"""Request for ReportConsentChange method. + + Attributes: + consent_change_action (google.cloud.discoveryengine_v1alpha.types.ReportConsentChangeRequest.ConsentChangeAction): + Required. Whether customer decides to accept + or decline service term. + At this moment, only accept action is supported. + project (str): + Required. Full resource name of a + [Project][google.cloud.discoveryengine.v1alpha.Project], + such as ``projects/{project_id_or_number}``. + service_term_id (str): + Required. The unique identifier of the terms of service to + update. Available term ids: + + - ``GA_DATA_USE_TERMS``: `Terms for data + use `__. + When using this service term id, the acceptable + [service_term_version][google.cloud.discoveryengine.v1alpha.ReportConsentChangeRequest.service_term_version] + to provide is ``2022-11-23``. + service_term_version (str): + Required. The version string of the terms of + service to update. + """ + + class ConsentChangeAction(proto.Enum): + r"""Type of consent acknowledgement (accept / reject). + + At this moment, only ``ACCEPT`` action is supported. + + Values: + CONSENT_CHANGE_ACTION_UNSPECIFIED (0): + Invalid action, user must specify + accept/decline + ACCEPT (1): + User accepts service terms. + """ + CONSENT_CHANGE_ACTION_UNSPECIFIED = 0 + ACCEPT = 1 + + consent_change_action: ConsentChangeAction = proto.Field( + proto.ENUM, + number=1, + enum=ConsentChangeAction, + ) + project: str = proto.Field( + proto.STRING, + number=2, + ) + service_term_id: str = proto.Field( + proto.STRING, + number=3, + ) + service_term_version: str = proto.Field( + proto.STRING, + number=4, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/rank_service.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/rank_service.py new file mode 100644 index 000000000000..f2cc0ac2ac0f --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/rank_service.py @@ -0,0 +1,152 @@ +# -*- 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.discoveryengine.v1alpha", + manifest={ + "RankingRecord", + "RankRequest", + "RankResponse", + }, +) + + +class RankingRecord(proto.Message): + r"""Record message for + [RankService.Rank][google.cloud.discoveryengine.v1alpha.RankService.Rank] + method. + + Attributes: + id (str): + The unique ID to represent the record. + title (str): + The title of the record. Empty by default. At least one of + [title][google.cloud.discoveryengine.v1alpha.RankingRecord.title] + or + [content][google.cloud.discoveryengine.v1alpha.RankingRecord.content] + should be set otherwise an INVALID_ARGUMENT error is thrown. + content (str): + The content of the record. Empty by default. At least one of + [title][google.cloud.discoveryengine.v1alpha.RankingRecord.title] + or + [content][google.cloud.discoveryengine.v1alpha.RankingRecord.content] + should be set otherwise an INVALID_ARGUMENT error is thrown. + score (float): + The score of this record based on the given + query and selected model. + """ + + id: str = proto.Field( + proto.STRING, + number=1, + ) + title: str = proto.Field( + proto.STRING, + number=2, + ) + content: str = proto.Field( + proto.STRING, + number=3, + ) + score: float = proto.Field( + proto.FLOAT, + number=4, + ) + + +class RankRequest(proto.Message): + r"""Request message for + [RankService.Rank][google.cloud.discoveryengine.v1alpha.RankService.Rank] + method. + + Attributes: + ranking_config (str): + Required. The resource name of the rank service config, such + as + ``projects/{project_num}/locations/{location_id}/rankingConfigs/default_ranking_config``. + model (str): + The identifier of the model to use. It is one of: + + - ``semantic-ranker-512@latest``: Semantic ranking model + with maxiumn input token size 512. + + It is set to ``semantic-ranker-512@latest`` by default if + unspecified. + top_n (int): + The number of results to return. If this is + unset or no bigger than zero, returns all + results. + query (str): + The query to use. + records (MutableSequence[google.cloud.discoveryengine_v1alpha.types.RankingRecord]): + Required. A list of records to rank. At most + 200 records to rank. + ignore_record_details_in_response (bool): + If true, the response will contain only + record ID and score. By default, it is false, + the response will contain record details. + """ + + ranking_config: str = proto.Field( + proto.STRING, + number=1, + ) + model: str = proto.Field( + proto.STRING, + number=2, + ) + top_n: int = proto.Field( + proto.INT32, + number=3, + ) + query: str = proto.Field( + proto.STRING, + number=4, + ) + records: MutableSequence["RankingRecord"] = proto.RepeatedField( + proto.MESSAGE, + number=5, + message="RankingRecord", + ) + ignore_record_details_in_response: bool = proto.Field( + proto.BOOL, + number=6, + ) + + +class RankResponse(proto.Message): + r"""Response message for + [RankService.Rank][google.cloud.discoveryengine.v1alpha.RankService.Rank] + method. + + Attributes: + records (MutableSequence[google.cloud.discoveryengine_v1alpha.types.RankingRecord]): + A list of records sorted by descending score. + """ + + records: MutableSequence["RankingRecord"] = proto.RepeatedField( + proto.MESSAGE, + number=5, + message="RankingRecord", + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/schema.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/schema.py index 641fc973aa96..2d8b06c94a3e 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/schema.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/schema.py @@ -237,6 +237,16 @@ class FieldConfig(proto.Message): If the schema field has a ``KeyPropertyMapping`` annotation, ``indexable_option`` and ``searchable_option`` of this field cannot be modified. + advanced_site_search_data_sources (MutableSequence[google.cloud.discoveryengine_v1alpha.types.FieldConfig.AdvancedSiteSearchDataSource]): + If this field is set, only the corresponding source will be + indexed for this field. Otherwise, the values from different + sources are merged. + + Assuming a page with ```` in meta tag, and + ```` in page map: if this enum is set to + METATAGS, we will only index ````; if this enum + is not set, we will merge them and index + ````. """ class FieldType(proto.Enum): @@ -367,6 +377,21 @@ class FilterableOption(proto.Enum): FILTERABLE_ENABLED = 1 FILTERABLE_DISABLED = 2 + class AdvancedSiteSearchDataSource(proto.Enum): + r"""Optional source of the advanced site search field. + + Values: + ADVANCED_SITE_SEARCH_DATA_SOURCE_UNSPECIFIED (0): + Value used when unset. + METATAGS (1): + Retrieve value from meta tag. + PAGEMAP (2): + Retrieve value from page map. + """ + ADVANCED_SITE_SEARCH_DATA_SOURCE_UNSPECIFIED = 0 + METATAGS = 1 + PAGEMAP = 2 + field_path: str = proto.Field( proto.STRING, number=1, @@ -410,6 +435,13 @@ class FilterableOption(proto.Enum): proto.STRING, number=7, ) + advanced_site_search_data_sources: MutableSequence[ + AdvancedSiteSearchDataSource + ] = proto.RepeatedField( + proto.ENUM, + number=10, + enum=AdvancedSiteSearchDataSource, + ) __all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/search_service.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/search_service.py index 04b7285f6d9a..7664384e0b73 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/search_service.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/search_service.py @@ -60,9 +60,15 @@ class SearchRequest(proto.Message): page_size (int): Maximum number of [Document][google.cloud.discoveryengine.v1alpha.Document]s - to return. If unspecified, defaults to a reasonable value. - The maximum allowed value is 100. Values above 100 are - coerced to 100. + to return. The maximum allowed value depends on the data + type. Values above the maximum value are coerced to the + maximum value. + + - Websites with basic indexing: Default ``10``, Maximum + ``25``. + - Websites with advanced indexing: Default ``25``, Maximum + ``50``. + - Other: Default ``50``, Maximum ``100``. If this field is negative, an ``INVALID_ARGUMENT`` is returned. @@ -204,7 +210,7 @@ class SearchRequest(proto.Message): If [SearchRequest.EmbeddingSpec.EmbeddingVector.field_path][google.cloud.discoveryengine.v1alpha.SearchRequest.EmbeddingSpec.EmbeddingVector.field_path] is not provided, it will use - [ServingConfig.EmbeddingConfig.field_path][]. + [ServingConfig.EmbeddingConfig.field_path][google.cloud.discoveryengine.v1alpha.ServingConfig.embedding_config]. ranking_expression (str): The ranking expression controls the customized ranking on retrieval documents. This overrides @@ -526,9 +532,131 @@ class ConditionBoostSpec(proto.Message): ranking, but it is not blocked out completely. Setting to 0.0 means no boost applied. The boosting - condition is ignored. + condition is ignored. Only one of the (condition, boost) + combination or the boost_control_spec below are set. If both + are set then the global boost is ignored and the more + fine-grained boost_control_spec is applied. + boost_control_spec (google.cloud.discoveryengine_v1alpha.types.SearchRequest.BoostSpec.ConditionBoostSpec.BoostControlSpec): + Complex specification for custom ranking + based on customer defined attribute value. """ + class BoostControlSpec(proto.Message): + r"""Specification for custom ranking based on customer specified + attribute value. It provides more controls for customized + ranking than the simple (condition, boost) combination above. + + Attributes: + field_name (str): + The name of the field whose value will be + used to determine the boost amount. + attribute_type (google.cloud.discoveryengine_v1alpha.types.SearchRequest.BoostSpec.ConditionBoostSpec.BoostControlSpec.AttributeType): + The attribute type to be used to determine the boost amount. + The attribute value can be derived from the field value of + the specified field_name. In the case of numerical it is + straightforward i.e. attribute_value = + numerical_field_value. In the case of freshness however, + attribute_value = (time.now() - datetime_field_value). + interpolation_type (google.cloud.discoveryengine_v1alpha.types.SearchRequest.BoostSpec.ConditionBoostSpec.BoostControlSpec.InterpolationType): + The interpolation type to be applied to + connect the control points listed below. + control_points (MutableSequence[google.cloud.discoveryengine_v1alpha.types.SearchRequest.BoostSpec.ConditionBoostSpec.BoostControlSpec.ControlPoint]): + The control points used to define the curve. The monotonic + function (defined through the interpolation_type above) + passes through the control points listed here. + """ + + class AttributeType(proto.Enum): + r"""The attribute(or function) for which the custom ranking is to + be applied. + + Values: + ATTRIBUTE_TYPE_UNSPECIFIED (0): + Unspecified AttributeType. + NUMERICAL (1): + The value of the numerical field will be used to dynamically + update the boost amount. In this case, the attribute_value + (the x value) of the control point will be the actual value + of the numerical field for which the boost_amount is + specified. + FRESHNESS (2): + For the freshness use case the attribute value will be the + duration between the current time and the date in the + datetime field specified. The value must be formatted as an + XSD ``dayTimeDuration`` value (a restricted subset of an ISO + 8601 duration value). The pattern for this is: + ``[nD][T[nH][nM][nS]]``. E.g. ``5D``, ``3DT12H30M``, + ``T24H``. + """ + ATTRIBUTE_TYPE_UNSPECIFIED = 0 + NUMERICAL = 1 + FRESHNESS = 2 + + class InterpolationType(proto.Enum): + r"""The interpolation type to be applied. Default will be linear + (Piecewise Linear). + + Values: + INTERPOLATION_TYPE_UNSPECIFIED (0): + Interpolation type is unspecified. In this + case, it defaults to Linear. + LINEAR (1): + Piecewise linear interpolation will be + applied. + """ + INTERPOLATION_TYPE_UNSPECIFIED = 0 + LINEAR = 1 + + class ControlPoint(proto.Message): + r"""The control points used to define the curve. The curve + defined through these control points can only be monotonically + increasing or decreasing(constant values are acceptable). + + Attributes: + attribute_value (str): + Can be one of: + + 1. The numerical field value. + 2. The duration spec for freshness: The value must be + formatted as an XSD ``dayTimeDuration`` value (a + restricted subset of an ISO 8601 duration value). The + pattern for this is: ``[nD][T[nH][nM][nS]]``. + boost_amount (float): + The value between -1 to 1 by which to boost the score if the + attribute_value evaluates to the value specified above. + """ + + attribute_value: str = proto.Field( + proto.STRING, + number=1, + ) + boost_amount: float = proto.Field( + proto.FLOAT, + number=2, + ) + + field_name: str = proto.Field( + proto.STRING, + number=1, + ) + attribute_type: "SearchRequest.BoostSpec.ConditionBoostSpec.BoostControlSpec.AttributeType" = proto.Field( + proto.ENUM, + number=2, + enum="SearchRequest.BoostSpec.ConditionBoostSpec.BoostControlSpec.AttributeType", + ) + interpolation_type: "SearchRequest.BoostSpec.ConditionBoostSpec.BoostControlSpec.InterpolationType" = proto.Field( + proto.ENUM, + number=3, + enum="SearchRequest.BoostSpec.ConditionBoostSpec.BoostControlSpec.InterpolationType", + ) + control_points: MutableSequence[ + "SearchRequest.BoostSpec.ConditionBoostSpec.BoostControlSpec.ControlPoint" + ] = proto.RepeatedField( + proto.MESSAGE, + number=4, + message="SearchRequest.BoostSpec.ConditionBoostSpec.BoostControlSpec.ControlPoint", + ) + condition: str = proto.Field( proto.STRING, number=1, @@ -537,6 +665,11 @@ class ConditionBoostSpec(proto.Message): proto.FLOAT, number=2, ) + boost_control_spec: "SearchRequest.BoostSpec.ConditionBoostSpec.BoostControlSpec" = proto.Field( + proto.MESSAGE, + number=3, + message="SearchRequest.BoostSpec.ConditionBoostSpec.BoostControlSpec", + ) condition_boost_specs: MutableSequence[ "SearchRequest.BoostSpec.ConditionBoostSpec" @@ -655,6 +788,12 @@ class ContentSearchSpec(proto.Message): - If [DataStore.DocumentProcessingConfig.chunking_config][] is specified, it defaults to ``CHUNKS``. - Otherwise, it defaults to ``DOCUMENTS``. + chunk_spec (google.cloud.discoveryengine_v1alpha.types.SearchRequest.ContentSearchSpec.ChunkSpec): + Specifies the chunk spec to be returned from the search + response. Only available if the + [SearchRequest.ContentSearchSpec.search_result_mode][google.cloud.discoveryengine.v1alpha.SearchRequest.ContentSearchSpec.search_result_mode] + is set to + [CHUNKS][google.cloud.discoveryengine.v1alpha.SearchRequest.ContentSearchSpec.SearchResultMode.CHUNKS] """ class SearchResultMode(proto.Enum): @@ -724,7 +863,12 @@ class SummarySpec(proto.Message): ``summaryResultCount``, the summary is generated from all of the results. - At most 10 results can be used to generate a summary. + At most 10 results for documents mode, or 50 for chunks + mode, can be used to generate a summary. The chunks mode is + used when + [SearchRequest.ContentSearchSpec.search_result_mode][google.cloud.discoveryengine.v1alpha.SearchRequest.ContentSearchSpec.search_result_mode] + is set to + [CHUNKS][google.cloud.discoveryengine.v1alpha.SearchRequest.ContentSearchSpec.SearchResultMode.CHUNKS]. include_citations (bool): Specifies whether to include citations in the summary. The default value is ``false``. @@ -781,6 +925,15 @@ class SummarySpec(proto.Message): model_spec (google.cloud.discoveryengine_v1alpha.types.SearchRequest.ContentSearchSpec.SummarySpec.ModelSpec): If specified, the spec will be used to modify the model specification provided to the LLM. + use_semantic_chunks (bool): + If true, answer will be generated from most + relevant chunks from top search results. This + feature will improve summary quality. Note that + with this feature enabled, not all top search + results will be referenced and included in the + reference list, so the citation source index + only points to the search results listed in the + reference list. """ class ModelPromptSpec(proto.Message): @@ -808,11 +961,14 @@ class ModelSpec(proto.Message): Supported values are: - ``stable``: string. Default value when no value is - specified. Uses a generally available, fine-tuned version - of the text-bison@001 model. - - ``preview``: string. (Public preview) Uses a fine-tuned - version of the text-bison@002 model. This model works - only for summaries in English. + specified. Uses a generally available, fine-tuned model. + For more information, see `Answer generation model + versions and + lifecycle `__. + - ``preview``: string. (Public preview) Uses a preview + model. For more information, see `Answer generation model + versions and + lifecycle `__. """ version: str = proto.Field( @@ -852,6 +1008,10 @@ class ModelSpec(proto.Message): message="SearchRequest.ContentSearchSpec.SummarySpec.ModelSpec", ) ) + use_semantic_chunks: bool = proto.Field( + proto.BOOL, + number=8, + ) class ExtractiveContentSpec(proto.Message): r"""A specification for configuring the extractive content in a @@ -895,12 +1055,10 @@ class ExtractiveContentSpec(proto.Message): ``max_extractive_segment_count``. return_extractive_segment_score (bool): Specifies whether to return the confidence score from the - extractive segments in each search result. The default value - is ``false``. - - Note: this is a priavte preview feature and only works for - allowlisted users, please reach out to Cloud Support team if - you want to use it. + extractive segments in each search result. This feature is + available only for new or allowlisted data stores. To + allowlist your data store, contact your Customer Engineer. + The default value is ``false``. num_previous_segments (int): Specifies whether to also include the adjacent from each selected segments. Return at most ``num_previous_segments`` @@ -931,6 +1089,35 @@ class ExtractiveContentSpec(proto.Message): number=5, ) + class ChunkSpec(proto.Message): + r"""Specifies the chunk spec to be returned from the search response. + Only available if the + [SearchRequest.ContentSearchSpec.search_result_mode][google.cloud.discoveryengine.v1alpha.SearchRequest.ContentSearchSpec.search_result_mode] + is set to + [CHUNKS][google.cloud.discoveryengine.v1alpha.SearchRequest.ContentSearchSpec.SearchResultMode.CHUNKS] + + Attributes: + num_previous_chunks (int): + The number of previous chunks to be returned + of the current chunk. The maximum allowed value + is 3. If not specified, no previous chunks will + be returned. + num_next_chunks (int): + The number of next chunks to be returned of + the current chunk. The maximum allowed value is + 3. If not specified, no next chunks will be + returned. + """ + + num_previous_chunks: int = proto.Field( + proto.INT32, + number=1, + ) + num_next_chunks: int = proto.Field( + proto.INT32, + number=2, + ) + snippet_spec: "SearchRequest.ContentSearchSpec.SnippetSpec" = proto.Field( proto.MESSAGE, number=1, @@ -953,6 +1140,11 @@ class ExtractiveContentSpec(proto.Message): enum="SearchRequest.ContentSearchSpec.SearchResultMode", ) ) + chunk_spec: "SearchRequest.ContentSearchSpec.ChunkSpec" = proto.Field( + proto.MESSAGE, + number=5, + message="SearchRequest.ContentSearchSpec.ChunkSpec", + ) class EmbeddingSpec(proto.Message): r"""The specification that uses customized query embedding vector @@ -1480,8 +1672,30 @@ class Reference(proto.Message): ``projects/*/locations/*/collections/*/dataStores/*/branches/*/documents/*``. uri (str): Cloud Storage or HTTP uri for the document. + chunk_contents (MutableSequence[google.cloud.discoveryengine_v1alpha.types.SearchResponse.Summary.Reference.ChunkContent]): + List of cited chunk contents derived from + document content. """ + class ChunkContent(proto.Message): + r"""Chunk content. + + Attributes: + content (str): + Chunk textual content. + page_identifier (str): + Page identifier. + """ + + content: str = proto.Field( + proto.STRING, + number=1, + ) + page_identifier: str = proto.Field( + proto.STRING, + number=2, + ) + title: str = proto.Field( proto.STRING, number=1, @@ -1494,6 +1708,13 @@ class Reference(proto.Message): proto.STRING, number=3, ) + chunk_contents: MutableSequence[ + "SearchResponse.Summary.Reference.ChunkContent" + ] = proto.RepeatedField( + proto.MESSAGE, + number=4, + message="SearchResponse.Summary.Reference.ChunkContent", + ) class SummaryWithMetadata(proto.Message): r"""Summary with metadata information. diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/search_tuning_service.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/search_tuning_service.py index d9ff396cb75a..e4e4183209cc 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/search_tuning_service.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/search_tuning_service.py @@ -72,8 +72,8 @@ class GcsTrainingInput(proto.Message): delimited jsonl/ndjson file. For search-tuning model, each line should have the \_id, - title and text. Example: {"_id": "doc1", title: "relevant - doc", "text": "relevant text"} + title and text. Example: + ``{"_id": "doc1", title: "relevant doc", "text": "relevant text"}`` query_data_path (str): The gcs query data which could be associated in train data. The data path format is @@ -158,8 +158,14 @@ class TrainCustomModelResponse(proto.Message): - **bad-data**: The training data quality is bad. - **no-improvement**: Tuning didn't improve performance. Won't deploy. - - **in-progress**: Model training is in progress. + - **in-progress**: Model training job creation is in + progress. + - **training**: Model is actively training. + - **evaluating**: The model is evaluating trained metrics. + - **indexing**: The model trained metrics are indexing. - **ready**: The model is ready for serving. + metrics (MutableMapping[str, float]): + The metrics of the trained model. """ error_samples: MutableSequence[status_pb2.Status] = proto.RepeatedField( @@ -176,6 +182,11 @@ class TrainCustomModelResponse(proto.Message): proto.STRING, number=3, ) + metrics: MutableMapping[str, float] = proto.MapField( + proto.STRING, + proto.DOUBLE, + number=4, + ) class TrainCustomModelMetadata(proto.Message): diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/session.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/session.py new file mode 100644 index 000000000000..9bac5bcd8a3f --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/session.py @@ -0,0 +1,140 @@ +# -*- 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 timestamp_pb2 # type: ignore +import proto # type: ignore + +__protobuf__ = proto.module( + package="google.cloud.discoveryengine.v1alpha", + manifest={ + "Session", + "Query", + }, +) + + +class Session(proto.Message): + r"""External session proto definition. + + Attributes: + name (str): + Immutable. Fully qualified name + ``projects/{project}/locations/global/collections/{collection}/engines/{engine}/sessions/*`` + state (google.cloud.discoveryengine_v1alpha.types.Session.State): + The state of the session. + user_pseudo_id (str): + A unique identifier for tracking users. + turns (MutableSequence[google.cloud.discoveryengine_v1alpha.types.Session.Turn]): + Turns. + start_time (google.protobuf.timestamp_pb2.Timestamp): + Output only. The time the session started. + end_time (google.protobuf.timestamp_pb2.Timestamp): + Output only. The time the session finished. + """ + + class State(proto.Enum): + r"""Enumeration of the state of the session. + + Values: + STATE_UNSPECIFIED (0): + State is unspecified. + IN_PROGRESS (1): + The session is currently open. + """ + STATE_UNSPECIFIED = 0 + IN_PROGRESS = 1 + + class Turn(proto.Message): + r"""Represents a turn, including a query from the user and a + answer from service. + + Attributes: + query (google.cloud.discoveryengine_v1alpha.types.Query): + The user query. + answer (str): + The resource name of the answer to the user + query. + """ + + query: "Query" = proto.Field( + proto.MESSAGE, + number=1, + message="Query", + ) + answer: str = proto.Field( + proto.STRING, + number=2, + ) + + name: str = proto.Field( + proto.STRING, + number=1, + ) + state: State = proto.Field( + proto.ENUM, + number=2, + enum=State, + ) + user_pseudo_id: str = proto.Field( + proto.STRING, + number=3, + ) + turns: MutableSequence[Turn] = proto.RepeatedField( + proto.MESSAGE, + number=4, + message=Turn, + ) + start_time: timestamp_pb2.Timestamp = proto.Field( + proto.MESSAGE, + number=5, + message=timestamp_pb2.Timestamp, + ) + end_time: timestamp_pb2.Timestamp = proto.Field( + proto.MESSAGE, + number=6, + message=timestamp_pb2.Timestamp, + ) + + +class Query(proto.Message): + r"""Defines a user inputed query. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + text (str): + Plain text. + + This field is a member of `oneof`_ ``content``. + query_id (str): + Unique Id for the query. + """ + + text: str = proto.Field( + proto.STRING, + number=2, + oneof="content", + ) + query_id: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/user_event.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/user_event.py index 6e8016804d21..5a84a19fb353 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/user_event.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1alpha/types/user_event.py @@ -363,7 +363,7 @@ class PageInfo(proto.Message): To represent full path of category, use '>' sign to separate different hierarchies. If '>' is part of the category name, - please replace it with other character(s). + replace it with other character(s). Category pages include special pages such as sales or promotions. For instance, a special sale page may have the diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/__init__.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/__init__.py index 6ab7b6c670d1..880db4a719b5 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/__init__.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/__init__.py @@ -32,6 +32,11 @@ ) from .services.document_service import DocumentServiceAsyncClient, DocumentServiceClient from .services.engine_service import EngineServiceAsyncClient, EngineServiceClient +from .services.grounded_generation_service import ( + GroundedGenerationServiceAsyncClient, + GroundedGenerationServiceClient, +) +from .services.rank_service import RankServiceAsyncClient, RankServiceClient from .services.recommendation_service import ( RecommendationServiceAsyncClient, RecommendationServiceClient, @@ -54,6 +59,7 @@ UserEventServiceAsyncClient, UserEventServiceClient, ) +from .types.answer import Answer from .types.common import ( CustomAttribute, DoubleList, @@ -75,14 +81,23 @@ TextInput, ) from .types.conversational_search_service import ( + AnswerQueryRequest, + AnswerQueryResponse, ConverseConversationRequest, ConverseConversationResponse, CreateConversationRequest, + CreateSessionRequest, DeleteConversationRequest, + DeleteSessionRequest, + GetAnswerRequest, GetConversationRequest, + GetSessionRequest, ListConversationsRequest, ListConversationsResponse, + ListSessionsRequest, + ListSessionsResponse, UpdateConversationRequest, + UpdateSessionRequest, ) from .types.data_store import DataStore from .types.data_store_service import ( @@ -114,10 +129,26 @@ GetEngineRequest, ListEnginesRequest, ListEnginesResponse, + PauseEngineRequest, + ResumeEngineRequest, + TuneEngineMetadata, + TuneEngineRequest, + TuneEngineResponse, UpdateEngineRequest, ) +from .types.grounded_generation_service import ( + CheckGroundingRequest, + CheckGroundingResponse, + CheckGroundingSpec, +) +from .types.grounding import FactChunk, GroundingFact from .types.import_config import ( BigQuerySource, + BigtableOptions, + BigtableSource, + CloudSqlSource, + FhirStoreSource, + FirestoreSource, GcsSource, ImportDocumentsMetadata, ImportDocumentsRequest, @@ -129,6 +160,7 @@ ImportUserEventsMetadata, ImportUserEventsRequest, ImportUserEventsResponse, + SpannerSource, ) from .types.purge_config import ( PurgeDocumentsMetadata, @@ -138,6 +170,7 @@ PurgeSuggestionDenyListEntriesRequest, PurgeSuggestionDenyListEntriesResponse, ) +from .types.rank_service import RankingRecord, RankRequest, RankResponse from .types.recommendation_service import RecommendRequest, RecommendResponse from .types.schema import Schema from .types.schema_service import ( @@ -164,6 +197,7 @@ ListServingConfigsResponse, UpdateServingConfigRequest, ) +from .types.session import Query, Session from .types.site_search_engine import SiteSearchEngine, SiteVerificationInfo, TargetSite from .types.site_search_engine_service import ( BatchCreateTargetSiteMetadata, @@ -212,6 +246,8 @@ "DataStoreServiceAsyncClient", "DocumentServiceAsyncClient", "EngineServiceAsyncClient", + "GroundedGenerationServiceAsyncClient", + "RankServiceAsyncClient", "RecommendationServiceAsyncClient", "SchemaServiceAsyncClient", "SearchServiceAsyncClient", @@ -219,6 +255,9 @@ "ServingConfigServiceAsyncClient", "SiteSearchEngineServiceAsyncClient", "UserEventServiceAsyncClient", + "Answer", + "AnswerQueryRequest", + "AnswerQueryResponse", "BatchCreateTargetSiteMetadata", "BatchCreateTargetSitesRequest", "BatchCreateTargetSitesResponse", @@ -226,6 +265,12 @@ "BatchVerifyTargetSitesRequest", "BatchVerifyTargetSitesResponse", "BigQuerySource", + "BigtableOptions", + "BigtableSource", + "CheckGroundingRequest", + "CheckGroundingResponse", + "CheckGroundingSpec", + "CloudSqlSource", "CollectUserEventRequest", "CompleteQueryRequest", "CompleteQueryResponse", @@ -245,6 +290,7 @@ "CreateEngineRequest", "CreateSchemaMetadata", "CreateSchemaRequest", + "CreateSessionRequest", "CreateTargetSiteMetadata", "CreateTargetSiteRequest", "CustomAttribute", @@ -258,6 +304,7 @@ "DeleteEngineRequest", "DeleteSchemaMetadata", "DeleteSchemaRequest", + "DeleteSessionRequest", "DeleteTargetSiteMetadata", "DeleteTargetSiteRequest", "DisableAdvancedSiteSearchMetadata", @@ -274,17 +321,24 @@ "EnableAdvancedSiteSearchResponse", "Engine", "EngineServiceClient", + "FactChunk", "FetchDomainVerificationStatusRequest", "FetchDomainVerificationStatusResponse", + "FhirStoreSource", + "FirestoreSource", "GcsSource", + "GetAnswerRequest", "GetConversationRequest", "GetDataStoreRequest", "GetDocumentRequest", "GetEngineRequest", "GetSchemaRequest", "GetServingConfigRequest", + "GetSessionRequest", "GetSiteSearchEngineRequest", "GetTargetSiteRequest", + "GroundedGenerationServiceClient", + "GroundingFact", "ImportDocumentsMetadata", "ImportDocumentsRequest", "ImportDocumentsResponse", @@ -309,17 +363,25 @@ "ListSchemasResponse", "ListServingConfigsRequest", "ListServingConfigsResponse", + "ListSessionsRequest", + "ListSessionsResponse", "ListTargetSitesRequest", "ListTargetSitesResponse", "MediaInfo", "PageInfo", "PanelInfo", + "PauseEngineRequest", "PurgeDocumentsMetadata", "PurgeDocumentsRequest", "PurgeDocumentsResponse", "PurgeSuggestionDenyListEntriesMetadata", "PurgeSuggestionDenyListEntriesRequest", "PurgeSuggestionDenyListEntriesResponse", + "Query", + "RankRequest", + "RankResponse", + "RankServiceClient", + "RankingRecord", "RecommendRequest", "RecommendResponse", "RecommendationServiceClient", @@ -327,6 +389,7 @@ "RecrawlUrisRequest", "RecrawlUrisResponse", "Reply", + "ResumeEngineRequest", "Schema", "SchemaServiceClient", "SearchAddOn", @@ -338,10 +401,12 @@ "SearchTuningServiceClient", "ServingConfig", "ServingConfigServiceClient", + "Session", "SiteSearchEngine", "SiteSearchEngineServiceClient", "SiteVerificationInfo", "SolutionType", + "SpannerSource", "SuggestionDenyListEntry", "TargetSite", "TextInput", @@ -349,6 +414,9 @@ "TrainCustomModelRequest", "TrainCustomModelResponse", "TransactionInfo", + "TuneEngineMetadata", + "TuneEngineRequest", + "TuneEngineResponse", "UpdateConversationRequest", "UpdateDataStoreRequest", "UpdateDocumentRequest", @@ -356,6 +424,7 @@ "UpdateSchemaMetadata", "UpdateSchemaRequest", "UpdateServingConfigRequest", + "UpdateSessionRequest", "UpdateTargetSiteMetadata", "UpdateTargetSiteRequest", "UserEvent", diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/gapic_metadata.json b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/gapic_metadata.json index eb48387bbb7a..739ee7f9b30f 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/gapic_metadata.json +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/gapic_metadata.json @@ -74,6 +74,11 @@ "grpc": { "libraryClient": "ConversationalSearchServiceClient", "rpcs": { + "AnswerQuery": { + "methods": [ + "answer_query" + ] + }, "ConverseConversation": { "methods": [ "converse_conversation" @@ -84,31 +89,66 @@ "create_conversation" ] }, + "CreateSession": { + "methods": [ + "create_session" + ] + }, "DeleteConversation": { "methods": [ "delete_conversation" ] }, + "DeleteSession": { + "methods": [ + "delete_session" + ] + }, + "GetAnswer": { + "methods": [ + "get_answer" + ] + }, "GetConversation": { "methods": [ "get_conversation" ] }, + "GetSession": { + "methods": [ + "get_session" + ] + }, "ListConversations": { "methods": [ "list_conversations" ] }, + "ListSessions": { + "methods": [ + "list_sessions" + ] + }, "UpdateConversation": { "methods": [ "update_conversation" ] + }, + "UpdateSession": { + "methods": [ + "update_session" + ] } } }, "grpc-async": { "libraryClient": "ConversationalSearchServiceAsyncClient", "rpcs": { + "AnswerQuery": { + "methods": [ + "answer_query" + ] + }, "ConverseConversation": { "methods": [ "converse_conversation" @@ -119,31 +159,66 @@ "create_conversation" ] }, + "CreateSession": { + "methods": [ + "create_session" + ] + }, "DeleteConversation": { "methods": [ "delete_conversation" ] }, + "DeleteSession": { + "methods": [ + "delete_session" + ] + }, + "GetAnswer": { + "methods": [ + "get_answer" + ] + }, "GetConversation": { "methods": [ "get_conversation" ] }, + "GetSession": { + "methods": [ + "get_session" + ] + }, "ListConversations": { "methods": [ "list_conversations" ] }, + "ListSessions": { + "methods": [ + "list_sessions" + ] + }, "UpdateConversation": { "methods": [ "update_conversation" ] + }, + "UpdateSession": { + "methods": [ + "update_session" + ] } } }, "rest": { "libraryClient": "ConversationalSearchServiceClient", "rpcs": { + "AnswerQuery": { + "methods": [ + "answer_query" + ] + }, "ConverseConversation": { "methods": [ "converse_conversation" @@ -154,25 +229,55 @@ "create_conversation" ] }, + "CreateSession": { + "methods": [ + "create_session" + ] + }, "DeleteConversation": { "methods": [ "delete_conversation" ] }, + "DeleteSession": { + "methods": [ + "delete_session" + ] + }, + "GetAnswer": { + "methods": [ + "get_answer" + ] + }, "GetConversation": { "methods": [ "get_conversation" ] }, + "GetSession": { + "methods": [ + "get_session" + ] + }, "ListConversations": { "methods": [ "list_conversations" ] }, + "ListSessions": { + "methods": [ + "list_sessions" + ] + }, "UpdateConversation": { "methods": [ "update_conversation" ] + }, + "UpdateSession": { + "methods": [ + "update_session" + ] } } } @@ -421,6 +526,21 @@ "list_engines" ] }, + "PauseEngine": { + "methods": [ + "pause_engine" + ] + }, + "ResumeEngine": { + "methods": [ + "resume_engine" + ] + }, + "TuneEngine": { + "methods": [ + "tune_engine" + ] + }, "UpdateEngine": { "methods": [ "update_engine" @@ -451,6 +571,21 @@ "list_engines" ] }, + "PauseEngine": { + "methods": [ + "pause_engine" + ] + }, + "ResumeEngine": { + "methods": [ + "resume_engine" + ] + }, + "TuneEngine": { + "methods": [ + "tune_engine" + ] + }, "UpdateEngine": { "methods": [ "update_engine" @@ -481,6 +616,21 @@ "list_engines" ] }, + "PauseEngine": { + "methods": [ + "pause_engine" + ] + }, + "ResumeEngine": { + "methods": [ + "resume_engine" + ] + }, + "TuneEngine": { + "methods": [ + "tune_engine" + ] + }, "UpdateEngine": { "methods": [ "update_engine" @@ -490,6 +640,74 @@ } } }, + "GroundedGenerationService": { + "clients": { + "grpc": { + "libraryClient": "GroundedGenerationServiceClient", + "rpcs": { + "CheckGrounding": { + "methods": [ + "check_grounding" + ] + } + } + }, + "grpc-async": { + "libraryClient": "GroundedGenerationServiceAsyncClient", + "rpcs": { + "CheckGrounding": { + "methods": [ + "check_grounding" + ] + } + } + }, + "rest": { + "libraryClient": "GroundedGenerationServiceClient", + "rpcs": { + "CheckGrounding": { + "methods": [ + "check_grounding" + ] + } + } + } + } + }, + "RankService": { + "clients": { + "grpc": { + "libraryClient": "RankServiceClient", + "rpcs": { + "Rank": { + "methods": [ + "rank" + ] + } + } + }, + "grpc-async": { + "libraryClient": "RankServiceAsyncClient", + "rpcs": { + "Rank": { + "methods": [ + "rank" + ] + } + } + }, + "rest": { + "libraryClient": "RankServiceClient", + "rpcs": { + "Rank": { + "methods": [ + "rank" + ] + } + } + } + } + }, "RecommendationService": { "clients": { "grpc": { diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/conversational_search_service/async_client.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/conversational_search_service/async_client.py index 1b279778445f..d7cc926366b0 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/conversational_search_service/async_client.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/conversational_search_service/async_client.py @@ -55,7 +55,10 @@ search_service, ) from google.cloud.discoveryengine_v1beta.types import conversation as gcd_conversation +from google.cloud.discoveryengine_v1beta.types import answer from google.cloud.discoveryengine_v1beta.types import conversation +from google.cloud.discoveryengine_v1beta.types import session +from google.cloud.discoveryengine_v1beta.types import session as gcd_session from .client import ConversationalSearchServiceClient from .transports.base import DEFAULT_CLIENT_INFO, ConversationalSearchServiceTransport @@ -76,6 +79,12 @@ class ConversationalSearchServiceAsyncClient: ) _DEFAULT_UNIVERSE = ConversationalSearchServiceClient._DEFAULT_UNIVERSE + answer_path = staticmethod(ConversationalSearchServiceClient.answer_path) + parse_answer_path = staticmethod( + ConversationalSearchServiceClient.parse_answer_path + ) + chunk_path = staticmethod(ConversationalSearchServiceClient.chunk_path) + parse_chunk_path = staticmethod(ConversationalSearchServiceClient.parse_chunk_path) conversation_path = staticmethod( ConversationalSearchServiceClient.conversation_path ) @@ -96,6 +105,10 @@ class ConversationalSearchServiceAsyncClient: parse_serving_config_path = staticmethod( ConversationalSearchServiceClient.parse_serving_config_path ) + session_path = staticmethod(ConversationalSearchServiceClient.session_path) + parse_session_path = staticmethod( + ConversationalSearchServiceClient.parse_session_path + ) common_billing_account_path = staticmethod( ConversationalSearchServiceClient.common_billing_account_path ) @@ -987,6 +1000,766 @@ async def sample_list_conversations(): # Done; return the response. return response + async def answer_query( + self, + request: Optional[ + Union[conversational_search_service.AnswerQueryRequest, dict] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> conversational_search_service.AnswerQueryResponse: + r"""Answer query method. + + .. 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 discoveryengine_v1beta + + async def sample_answer_query(): + # Create a client + client = discoveryengine_v1beta.ConversationalSearchServiceAsyncClient() + + # Initialize request argument(s) + query = discoveryengine_v1beta.Query() + query.text = "text_value" + + request = discoveryengine_v1beta.AnswerQueryRequest( + serving_config="serving_config_value", + query=query, + ) + + # Make the request + response = await client.answer_query(request=request) + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.discoveryengine_v1beta.types.AnswerQueryRequest, dict]]): + The request object. Request message for + [ConversationalSearchService.AnswerQuery][google.cloud.discoveryengine.v1beta.ConversationalSearchService.AnswerQuery] + 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.cloud.discoveryengine_v1beta.types.AnswerQueryResponse: + Response message for + [ConversationalSearchService.AnswerQuery][google.cloud.discoveryengine.v1beta.ConversationalSearchService.AnswerQuery] + method. + + """ + # Create or coerce a protobuf request object. + request = conversational_search_service.AnswerQueryRequest(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.answer_query, + 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( + (("serving_config", request.serving_config),) + ), + ) + + # 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_answer( + self, + request: Optional[ + Union[conversational_search_service.GetAnswerRequest, 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]] = (), + ) -> answer.Answer: + r"""Gets a Answer. + + .. 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 discoveryengine_v1beta + + async def sample_get_answer(): + # Create a client + client = discoveryengine_v1beta.ConversationalSearchServiceAsyncClient() + + # Initialize request argument(s) + request = discoveryengine_v1beta.GetAnswerRequest( + name="name_value", + ) + + # Make the request + response = await client.get_answer(request=request) + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.discoveryengine_v1beta.types.GetAnswerRequest, dict]]): + The request object. Request for GetAnswer method. + name (:class:`str`): + Required. The resource name of the Answer to get. + Format: + ``projects/{project_number}/locations/{location_id}/collections/{collection}/engines/{engine_id}/sessions/{session_id}/answers/{answer_id}`` + + 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.discoveryengine_v1beta.types.Answer: + Defines an answer. + """ + # 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." + ) + + request = conversational_search_service.GetAnswerRequest(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 = gapic_v1.method_async.wrap_method( + self._client._transport.get_answer, + 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 create_session( + self, + request: Optional[ + Union[conversational_search_service.CreateSessionRequest, dict] + ] = None, + *, + parent: Optional[str] = None, + session: Optional[gcd_session.Session] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> gcd_session.Session: + r"""Creates a Session. + + If the [Session][google.cloud.discoveryengine.v1beta.Session] to + create already exists, an ALREADY_EXISTS error is returned. + + .. 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 discoveryengine_v1beta + + async def sample_create_session(): + # Create a client + client = discoveryengine_v1beta.ConversationalSearchServiceAsyncClient() + + # Initialize request argument(s) + request = discoveryengine_v1beta.CreateSessionRequest( + parent="parent_value", + ) + + # Make the request + response = await client.create_session(request=request) + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.discoveryengine_v1beta.types.CreateSessionRequest, dict]]): + The request object. Request for CreateSession method. + parent (:class:`str`): + Required. Full resource name of parent data store. + Format: + ``projects/{project_number}/locations/{location_id}/collections/{collection}/dataStores/{data_store_id}`` + + This corresponds to the ``parent`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + session (:class:`google.cloud.discoveryengine_v1beta.types.Session`): + Required. The session to create. + This corresponds to the ``session`` 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.discoveryengine_v1beta.types.Session: + External session proto definition. + """ + # 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, session]) + 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." + ) + + request = conversational_search_service.CreateSessionRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if parent is not None: + request.parent = parent + if session is not None: + request.session = session + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = gapic_v1.method_async.wrap_method( + self._client._transport.create_session, + 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((("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 delete_session( + self, + request: Optional[ + Union[conversational_search_service.DeleteSessionRequest, 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]] = (), + ) -> None: + r"""Deletes a Session. + + If the [Session][google.cloud.discoveryengine.v1beta.Session] to + delete does not exist, a NOT_FOUND error is returned. + + .. 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 discoveryengine_v1beta + + async def sample_delete_session(): + # Create a client + client = discoveryengine_v1beta.ConversationalSearchServiceAsyncClient() + + # Initialize request argument(s) + request = discoveryengine_v1beta.DeleteSessionRequest( + name="name_value", + ) + + # Make the request + await client.delete_session(request=request) + + Args: + request (Optional[Union[google.cloud.discoveryengine_v1beta.types.DeleteSessionRequest, dict]]): + The request object. Request for DeleteSession method. + name (:class:`str`): + Required. The resource name of the Session to delete. + Format: + ``projects/{project_number}/locations/{location_id}/collections/{collection}/dataStores/{data_store_id}/sessions/{session_id}`` + + 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. + """ + # 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." + ) + + request = conversational_search_service.DeleteSessionRequest(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 = gapic_v1.method_async.wrap_method( + self._client._transport.delete_session, + 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. + await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + async def update_session( + self, + request: Optional[ + Union[conversational_search_service.UpdateSessionRequest, dict] + ] = None, + *, + session: Optional[gcd_session.Session] = 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]] = (), + ) -> gcd_session.Session: + r"""Updates a Session. + + [Session][google.cloud.discoveryengine.v1beta.Session] action + type cannot be changed. If the + [Session][google.cloud.discoveryengine.v1beta.Session] to update + does not exist, a NOT_FOUND error is returned. + + .. 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 discoveryengine_v1beta + + async def sample_update_session(): + # Create a client + client = discoveryengine_v1beta.ConversationalSearchServiceAsyncClient() + + # Initialize request argument(s) + request = discoveryengine_v1beta.UpdateSessionRequest( + ) + + # Make the request + response = await client.update_session(request=request) + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.discoveryengine_v1beta.types.UpdateSessionRequest, dict]]): + The request object. Request for UpdateSession method. + session (:class:`google.cloud.discoveryengine_v1beta.types.Session`): + Required. The Session to update. + This corresponds to the ``session`` 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 + [Session][google.cloud.discoveryengine.v1beta.Session] + to update. The following are NOT supported: + + - [Session.name][google.cloud.discoveryengine.v1beta.Session.name] + + 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.discoveryengine_v1beta.types.Session: + External session proto definition. + """ + # 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([session, 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." + ) + + request = conversational_search_service.UpdateSessionRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if session is not None: + request.session = session + 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 = gapic_v1.method_async.wrap_method( + self._client._transport.update_session, + 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( + (("session.name", request.session.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_session( + self, + request: Optional[ + Union[conversational_search_service.GetSessionRequest, 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]] = (), + ) -> session.Session: + r"""Gets a Session. + + .. 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 discoveryengine_v1beta + + async def sample_get_session(): + # Create a client + client = discoveryengine_v1beta.ConversationalSearchServiceAsyncClient() + + # Initialize request argument(s) + request = discoveryengine_v1beta.GetSessionRequest( + name="name_value", + ) + + # Make the request + response = await client.get_session(request=request) + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.discoveryengine_v1beta.types.GetSessionRequest, dict]]): + The request object. Request for GetSession method. + name (:class:`str`): + Required. The resource name of the Session to get. + Format: + ``projects/{project_number}/locations/{location_id}/collections/{collection}/dataStores/{data_store_id}/sessions/{session_id}`` + + 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.discoveryengine_v1beta.types.Session: + External session proto definition. + """ + # 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." + ) + + request = conversational_search_service.GetSessionRequest(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 = gapic_v1.method_async.wrap_method( + self._client._transport.get_session, + 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 list_sessions( + self, + request: Optional[ + Union[conversational_search_service.ListSessionsRequest, 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]] = (), + ) -> pagers.ListSessionsAsyncPager: + r"""Lists all Sessions by their parent + [DataStore][google.cloud.discoveryengine.v1beta.DataStore]. + + .. 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 discoveryengine_v1beta + + async def sample_list_sessions(): + # Create a client + client = discoveryengine_v1beta.ConversationalSearchServiceAsyncClient() + + # Initialize request argument(s) + request = discoveryengine_v1beta.ListSessionsRequest( + parent="parent_value", + ) + + # Make the request + page_result = client.list_sessions(request=request) + + # Handle the response + async for response in page_result: + print(response) + + Args: + request (Optional[Union[google.cloud.discoveryengine_v1beta.types.ListSessionsRequest, dict]]): + The request object. Request for ListSessions method. + parent (:class:`str`): + Required. The data store resource name. Format: + ``projects/{project_number}/locations/{location_id}/collections/{collection}/dataStores/{data_store_id}`` + + 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.discoveryengine_v1beta.services.conversational_search_service.pagers.ListSessionsAsyncPager: + Response for ListSessions method. + + Iterating over this object will yield + results and resolve additional pages + automatically. + + """ + # 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." + ) + + request = conversational_search_service.ListSessionsRequest(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 = gapic_v1.method_async.wrap_method( + self._client._transport.list_sessions, + 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((("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, + ) + + # This method is paged; wrap the response in a pager, which provides + # an `__aiter__` convenience method. + response = pagers.ListSessionsAsyncPager( + method=rpc, + request=request, + response=response, + metadata=metadata, + ) + + # Done; return the response. + return response + async def list_operations( self, request: Optional[operations_pb2.ListOperationsRequest] = None, diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/conversational_search_service/client.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/conversational_search_service/client.py index dcc464ae7c7e..ecb63e742002 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/conversational_search_service/client.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/conversational_search_service/client.py @@ -60,7 +60,10 @@ search_service, ) from google.cloud.discoveryengine_v1beta.types import conversation as gcd_conversation +from google.cloud.discoveryengine_v1beta.types import answer from google.cloud.discoveryengine_v1beta.types import conversation +from google.cloud.discoveryengine_v1beta.types import session +from google.cloud.discoveryengine_v1beta.types import session as gcd_session from .transports.base import DEFAULT_CLIENT_INFO, ConversationalSearchServiceTransport from .transports.grpc import ConversationalSearchServiceGrpcTransport @@ -198,6 +201,60 @@ def transport(self) -> ConversationalSearchServiceTransport: """ return self._transport + @staticmethod + def answer_path( + project: str, + location: str, + data_store: str, + session: str, + answer: str, + ) -> str: + """Returns a fully-qualified answer string.""" + return "projects/{project}/locations/{location}/dataStores/{data_store}/sessions/{session}/answers/{answer}".format( + project=project, + location=location, + data_store=data_store, + session=session, + answer=answer, + ) + + @staticmethod + def parse_answer_path(path: str) -> Dict[str, str]: + """Parses a answer path into its component segments.""" + m = re.match( + r"^projects/(?P.+?)/locations/(?P.+?)/dataStores/(?P.+?)/sessions/(?P.+?)/answers/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def chunk_path( + project: str, + location: str, + data_store: str, + branch: str, + document: str, + chunk: str, + ) -> str: + """Returns a fully-qualified chunk string.""" + return "projects/{project}/locations/{location}/dataStores/{data_store}/branches/{branch}/documents/{document}/chunks/{chunk}".format( + project=project, + location=location, + data_store=data_store, + branch=branch, + document=document, + chunk=chunk, + ) + + @staticmethod + def parse_chunk_path(path: str) -> Dict[str, str]: + """Parses a chunk path into its component segments.""" + m = re.match( + r"^projects/(?P.+?)/locations/(?P.+?)/dataStores/(?P.+?)/branches/(?P.+?)/documents/(?P.+?)/chunks/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + @staticmethod def conversation_path( project: str, @@ -294,6 +351,30 @@ def parse_serving_config_path(path: str) -> Dict[str, str]: ) return m.groupdict() if m else {} + @staticmethod + def session_path( + project: str, + location: str, + data_store: str, + session: str, + ) -> str: + """Returns a fully-qualified session string.""" + return "projects/{project}/locations/{location}/dataStores/{data_store}/sessions/{session}".format( + project=project, + location=location, + data_store=data_store, + session=session, + ) + + @staticmethod + def parse_session_path(path: str) -> Dict[str, str]: + """Parses a session path into its component segments.""" + m = re.match( + r"^projects/(?P.+?)/locations/(?P.+?)/dataStores/(?P.+?)/sessions/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + @staticmethod def common_billing_account_path( billing_account: str, @@ -1467,6 +1548,767 @@ def sample_list_conversations(): # Done; return the response. return response + def answer_query( + self, + request: Optional[ + Union[conversational_search_service.AnswerQueryRequest, dict] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> conversational_search_service.AnswerQueryResponse: + r"""Answer query method. + + .. 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 discoveryengine_v1beta + + def sample_answer_query(): + # Create a client + client = discoveryengine_v1beta.ConversationalSearchServiceClient() + + # Initialize request argument(s) + query = discoveryengine_v1beta.Query() + query.text = "text_value" + + request = discoveryengine_v1beta.AnswerQueryRequest( + serving_config="serving_config_value", + query=query, + ) + + # Make the request + response = client.answer_query(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.discoveryengine_v1beta.types.AnswerQueryRequest, dict]): + The request object. Request message for + [ConversationalSearchService.AnswerQuery][google.cloud.discoveryengine.v1beta.ConversationalSearchService.AnswerQuery] + 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.cloud.discoveryengine_v1beta.types.AnswerQueryResponse: + Response message for + [ConversationalSearchService.AnswerQuery][google.cloud.discoveryengine.v1beta.ConversationalSearchService.AnswerQuery] + method. + + """ + # Create or coerce a protobuf request object. + # Minor optimization to avoid making a copy if the user passes + # in a conversational_search_service.AnswerQueryRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance(request, conversational_search_service.AnswerQueryRequest): + request = conversational_search_service.AnswerQueryRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.answer_query] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("serving_config", request.serving_config),) + ), + ) + + # 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_answer( + self, + request: Optional[ + Union[conversational_search_service.GetAnswerRequest, 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]] = (), + ) -> answer.Answer: + r"""Gets a Answer. + + .. 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 discoveryengine_v1beta + + def sample_get_answer(): + # Create a client + client = discoveryengine_v1beta.ConversationalSearchServiceClient() + + # Initialize request argument(s) + request = discoveryengine_v1beta.GetAnswerRequest( + name="name_value", + ) + + # Make the request + response = client.get_answer(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.discoveryengine_v1beta.types.GetAnswerRequest, dict]): + The request object. Request for GetAnswer method. + name (str): + Required. The resource name of the Answer to get. + Format: + ``projects/{project_number}/locations/{location_id}/collections/{collection}/engines/{engine_id}/sessions/{session_id}/answers/{answer_id}`` + + 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.discoveryengine_v1beta.types.Answer: + Defines an answer. + """ + # 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." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a conversational_search_service.GetAnswerRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance(request, conversational_search_service.GetAnswerRequest): + request = conversational_search_service.GetAnswerRequest(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_answer] + + # 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 create_session( + self, + request: Optional[ + Union[conversational_search_service.CreateSessionRequest, dict] + ] = None, + *, + parent: Optional[str] = None, + session: Optional[gcd_session.Session] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> gcd_session.Session: + r"""Creates a Session. + + If the [Session][google.cloud.discoveryengine.v1beta.Session] to + create already exists, an ALREADY_EXISTS error is returned. + + .. 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 discoveryengine_v1beta + + def sample_create_session(): + # Create a client + client = discoveryengine_v1beta.ConversationalSearchServiceClient() + + # Initialize request argument(s) + request = discoveryengine_v1beta.CreateSessionRequest( + parent="parent_value", + ) + + # Make the request + response = client.create_session(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.discoveryengine_v1beta.types.CreateSessionRequest, dict]): + The request object. Request for CreateSession method. + parent (str): + Required. Full resource name of parent data store. + Format: + ``projects/{project_number}/locations/{location_id}/collections/{collection}/dataStores/{data_store_id}`` + + This corresponds to the ``parent`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + session (google.cloud.discoveryengine_v1beta.types.Session): + Required. The session to create. + This corresponds to the ``session`` 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.discoveryengine_v1beta.types.Session: + External session proto definition. + """ + # 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, session]) + 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." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a conversational_search_service.CreateSessionRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance(request, conversational_search_service.CreateSessionRequest): + request = conversational_search_service.CreateSessionRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if parent is not None: + request.parent = parent + if session is not None: + request.session = session + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.create_session] + + # 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 delete_session( + self, + request: Optional[ + Union[conversational_search_service.DeleteSessionRequest, 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]] = (), + ) -> None: + r"""Deletes a Session. + + If the [Session][google.cloud.discoveryengine.v1beta.Session] to + delete does not exist, a NOT_FOUND error is returned. + + .. 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 discoveryengine_v1beta + + def sample_delete_session(): + # Create a client + client = discoveryengine_v1beta.ConversationalSearchServiceClient() + + # Initialize request argument(s) + request = discoveryengine_v1beta.DeleteSessionRequest( + name="name_value", + ) + + # Make the request + client.delete_session(request=request) + + Args: + request (Union[google.cloud.discoveryengine_v1beta.types.DeleteSessionRequest, dict]): + The request object. Request for DeleteSession method. + name (str): + Required. The resource name of the Session to delete. + Format: + ``projects/{project_number}/locations/{location_id}/collections/{collection}/dataStores/{data_store_id}/sessions/{session_id}`` + + 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. + """ + # 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." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a conversational_search_service.DeleteSessionRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance(request, conversational_search_service.DeleteSessionRequest): + request = conversational_search_service.DeleteSessionRequest(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.delete_session] + + # 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. + rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + def update_session( + self, + request: Optional[ + Union[conversational_search_service.UpdateSessionRequest, dict] + ] = None, + *, + session: Optional[gcd_session.Session] = 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]] = (), + ) -> gcd_session.Session: + r"""Updates a Session. + + [Session][google.cloud.discoveryengine.v1beta.Session] action + type cannot be changed. If the + [Session][google.cloud.discoveryengine.v1beta.Session] to update + does not exist, a NOT_FOUND error is returned. + + .. 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 discoveryengine_v1beta + + def sample_update_session(): + # Create a client + client = discoveryengine_v1beta.ConversationalSearchServiceClient() + + # Initialize request argument(s) + request = discoveryengine_v1beta.UpdateSessionRequest( + ) + + # Make the request + response = client.update_session(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.discoveryengine_v1beta.types.UpdateSessionRequest, dict]): + The request object. Request for UpdateSession method. + session (google.cloud.discoveryengine_v1beta.types.Session): + Required. The Session to update. + This corresponds to the ``session`` 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 + [Session][google.cloud.discoveryengine.v1beta.Session] + to update. The following are NOT supported: + + - [Session.name][google.cloud.discoveryengine.v1beta.Session.name] + + 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.discoveryengine_v1beta.types.Session: + External session proto definition. + """ + # 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([session, 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." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a conversational_search_service.UpdateSessionRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance(request, conversational_search_service.UpdateSessionRequest): + request = conversational_search_service.UpdateSessionRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if session is not None: + request.session = session + 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_session] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("session.name", request.session.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_session( + self, + request: Optional[ + Union[conversational_search_service.GetSessionRequest, 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]] = (), + ) -> session.Session: + r"""Gets a Session. + + .. 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 discoveryengine_v1beta + + def sample_get_session(): + # Create a client + client = discoveryengine_v1beta.ConversationalSearchServiceClient() + + # Initialize request argument(s) + request = discoveryengine_v1beta.GetSessionRequest( + name="name_value", + ) + + # Make the request + response = client.get_session(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.discoveryengine_v1beta.types.GetSessionRequest, dict]): + The request object. Request for GetSession method. + name (str): + Required. The resource name of the Session to get. + Format: + ``projects/{project_number}/locations/{location_id}/collections/{collection}/dataStores/{data_store_id}/sessions/{session_id}`` + + 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.discoveryengine_v1beta.types.Session: + External session proto definition. + """ + # 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." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a conversational_search_service.GetSessionRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance(request, conversational_search_service.GetSessionRequest): + request = conversational_search_service.GetSessionRequest(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_session] + + # 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 list_sessions( + self, + request: Optional[ + Union[conversational_search_service.ListSessionsRequest, 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]] = (), + ) -> pagers.ListSessionsPager: + r"""Lists all Sessions by their parent + [DataStore][google.cloud.discoveryengine.v1beta.DataStore]. + + .. 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 discoveryengine_v1beta + + def sample_list_sessions(): + # Create a client + client = discoveryengine_v1beta.ConversationalSearchServiceClient() + + # Initialize request argument(s) + request = discoveryengine_v1beta.ListSessionsRequest( + parent="parent_value", + ) + + # Make the request + page_result = client.list_sessions(request=request) + + # Handle the response + for response in page_result: + print(response) + + Args: + request (Union[google.cloud.discoveryengine_v1beta.types.ListSessionsRequest, dict]): + The request object. Request for ListSessions method. + parent (str): + Required. The data store resource name. Format: + ``projects/{project_number}/locations/{location_id}/collections/{collection}/dataStores/{data_store_id}`` + + 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.discoveryengine_v1beta.services.conversational_search_service.pagers.ListSessionsPager: + Response for ListSessions method. + + Iterating over this object will yield + results and resolve additional pages + automatically. + + """ + # 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." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a conversational_search_service.ListSessionsRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance(request, conversational_search_service.ListSessionsRequest): + request = conversational_search_service.ListSessionsRequest(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_sessions] + + # 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, + ) + + # This method is paged; wrap the response in a pager, which provides + # an `__iter__` convenience method. + response = pagers.ListSessionsPager( + method=rpc, + request=request, + response=response, + metadata=metadata, + ) + + # Done; return the response. + return response + def __enter__(self) -> "ConversationalSearchServiceClient": return self diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/conversational_search_service/pagers.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/conversational_search_service/pagers.py index 0d00e42219e7..0d4edbf00010 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/conversational_search_service/pagers.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/conversational_search_service/pagers.py @@ -27,6 +27,7 @@ from google.cloud.discoveryengine_v1beta.types import ( conversation, conversational_search_service, + session, ) @@ -162,3 +163,135 @@ async def async_generator(): def __repr__(self) -> str: return "{0}<{1!r}>".format(self.__class__.__name__, self._response) + + +class ListSessionsPager: + """A pager for iterating through ``list_sessions`` requests. + + This class thinly wraps an initial + :class:`google.cloud.discoveryengine_v1beta.types.ListSessionsResponse` object, and + provides an ``__iter__`` method to iterate through its + ``sessions`` field. + + If there are more pages, the ``__iter__`` method will make additional + ``ListSessions`` requests and continue to iterate + through the ``sessions`` field on the + corresponding responses. + + All the usual :class:`google.cloud.discoveryengine_v1beta.types.ListSessionsResponse` + attributes are available on the pager. If multiple requests are made, only + the most recent response is retained, and thus used for attribute lookup. + """ + + def __init__( + self, + method: Callable[..., conversational_search_service.ListSessionsResponse], + request: conversational_search_service.ListSessionsRequest, + response: conversational_search_service.ListSessionsResponse, + *, + metadata: Sequence[Tuple[str, str]] = () + ): + """Instantiate the pager. + + Args: + method (Callable): The method that was originally called, and + which instantiated this pager. + request (google.cloud.discoveryengine_v1beta.types.ListSessionsRequest): + The initial request object. + response (google.cloud.discoveryengine_v1beta.types.ListSessionsResponse): + The initial response object. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + """ + self._method = method + self._request = conversational_search_service.ListSessionsRequest(request) + self._response = response + self._metadata = metadata + + def __getattr__(self, name: str) -> Any: + return getattr(self._response, name) + + @property + def pages(self) -> Iterator[conversational_search_service.ListSessionsResponse]: + yield self._response + while self._response.next_page_token: + self._request.page_token = self._response.next_page_token + self._response = self._method(self._request, metadata=self._metadata) + yield self._response + + def __iter__(self) -> Iterator[session.Session]: + for page in self.pages: + yield from page.sessions + + def __repr__(self) -> str: + return "{0}<{1!r}>".format(self.__class__.__name__, self._response) + + +class ListSessionsAsyncPager: + """A pager for iterating through ``list_sessions`` requests. + + This class thinly wraps an initial + :class:`google.cloud.discoveryengine_v1beta.types.ListSessionsResponse` object, and + provides an ``__aiter__`` method to iterate through its + ``sessions`` field. + + If there are more pages, the ``__aiter__`` method will make additional + ``ListSessions`` requests and continue to iterate + through the ``sessions`` field on the + corresponding responses. + + All the usual :class:`google.cloud.discoveryengine_v1beta.types.ListSessionsResponse` + attributes are available on the pager. If multiple requests are made, only + the most recent response is retained, and thus used for attribute lookup. + """ + + def __init__( + self, + method: Callable[ + ..., Awaitable[conversational_search_service.ListSessionsResponse] + ], + request: conversational_search_service.ListSessionsRequest, + response: conversational_search_service.ListSessionsResponse, + *, + metadata: Sequence[Tuple[str, str]] = () + ): + """Instantiates the pager. + + Args: + method (Callable): The method that was originally called, and + which instantiated this pager. + request (google.cloud.discoveryengine_v1beta.types.ListSessionsRequest): + The initial request object. + response (google.cloud.discoveryengine_v1beta.types.ListSessionsResponse): + The initial response object. + metadata (Sequence[Tuple[str, str]]): Strings which should be + sent along with the request as metadata. + """ + self._method = method + self._request = conversational_search_service.ListSessionsRequest(request) + self._response = response + self._metadata = metadata + + def __getattr__(self, name: str) -> Any: + return getattr(self._response, name) + + @property + async def pages( + self, + ) -> AsyncIterator[conversational_search_service.ListSessionsResponse]: + yield self._response + while self._response.next_page_token: + self._request.page_token = self._response.next_page_token + self._response = await self._method(self._request, metadata=self._metadata) + yield self._response + + def __aiter__(self) -> AsyncIterator[session.Session]: + async def async_generator(): + async for page in self.pages: + for response in page.sessions: + yield response + + return async_generator() + + def __repr__(self) -> str: + return "{0}<{1!r}>".format(self.__class__.__name__, self._response) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/conversational_search_service/transports/base.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/conversational_search_service/transports/base.py index 0cfee37cbd99..2b07aafb2682 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/conversational_search_service/transports/base.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/conversational_search_service/transports/base.py @@ -30,7 +30,10 @@ from google.cloud.discoveryengine_v1beta import gapic_version as package_version from google.cloud.discoveryengine_v1beta.types import conversation as gcd_conversation from google.cloud.discoveryengine_v1beta.types import conversational_search_service +from google.cloud.discoveryengine_v1beta.types import answer from google.cloud.discoveryengine_v1beta.types import conversation +from google.cloud.discoveryengine_v1beta.types import session +from google.cloud.discoveryengine_v1beta.types import session as gcd_session DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( gapic_version=package_version.__version__ @@ -161,6 +164,41 @@ def _prep_wrapped_messages(self, client_info): default_timeout=None, client_info=client_info, ), + self.answer_query: gapic_v1.method.wrap_method( + self.answer_query, + default_timeout=None, + client_info=client_info, + ), + self.get_answer: gapic_v1.method.wrap_method( + self.get_answer, + default_timeout=None, + client_info=client_info, + ), + self.create_session: gapic_v1.method.wrap_method( + self.create_session, + default_timeout=None, + client_info=client_info, + ), + self.delete_session: gapic_v1.method.wrap_method( + self.delete_session, + default_timeout=None, + client_info=client_info, + ), + self.update_session: gapic_v1.method.wrap_method( + self.update_session, + default_timeout=None, + client_info=client_info, + ), + self.get_session: gapic_v1.method.wrap_method( + self.get_session, + default_timeout=None, + client_info=client_info, + ), + self.list_sessions: gapic_v1.method.wrap_method( + self.list_sessions, + default_timeout=None, + client_info=client_info, + ), } def close(self): @@ -232,6 +270,75 @@ def list_conversations( ]: raise NotImplementedError() + @property + def answer_query( + self, + ) -> Callable[ + [conversational_search_service.AnswerQueryRequest], + Union[ + conversational_search_service.AnswerQueryResponse, + Awaitable[conversational_search_service.AnswerQueryResponse], + ], + ]: + raise NotImplementedError() + + @property + def get_answer( + self, + ) -> Callable[ + [conversational_search_service.GetAnswerRequest], + Union[answer.Answer, Awaitable[answer.Answer]], + ]: + raise NotImplementedError() + + @property + def create_session( + self, + ) -> Callable[ + [conversational_search_service.CreateSessionRequest], + Union[gcd_session.Session, Awaitable[gcd_session.Session]], + ]: + raise NotImplementedError() + + @property + def delete_session( + self, + ) -> Callable[ + [conversational_search_service.DeleteSessionRequest], + Union[empty_pb2.Empty, Awaitable[empty_pb2.Empty]], + ]: + raise NotImplementedError() + + @property + def update_session( + self, + ) -> Callable[ + [conversational_search_service.UpdateSessionRequest], + Union[gcd_session.Session, Awaitable[gcd_session.Session]], + ]: + raise NotImplementedError() + + @property + def get_session( + self, + ) -> Callable[ + [conversational_search_service.GetSessionRequest], + Union[session.Session, Awaitable[session.Session]], + ]: + raise NotImplementedError() + + @property + def list_sessions( + self, + ) -> Callable[ + [conversational_search_service.ListSessionsRequest], + Union[ + conversational_search_service.ListSessionsResponse, + Awaitable[conversational_search_service.ListSessionsResponse], + ], + ]: + raise NotImplementedError() + @property def list_operations( self, diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/conversational_search_service/transports/grpc.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/conversational_search_service/transports/grpc.py index afe3d4fcdde5..798d0bca63f8 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/conversational_search_service/transports/grpc.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/conversational_search_service/transports/grpc.py @@ -27,7 +27,10 @@ from google.cloud.discoveryengine_v1beta.types import conversation as gcd_conversation from google.cloud.discoveryengine_v1beta.types import conversational_search_service +from google.cloud.discoveryengine_v1beta.types import answer from google.cloud.discoveryengine_v1beta.types import conversation +from google.cloud.discoveryengine_v1beta.types import session +from google.cloud.discoveryengine_v1beta.types import session as gcd_session from .base import DEFAULT_CLIENT_INFO, ConversationalSearchServiceTransport @@ -420,6 +423,212 @@ def list_conversations( ) return self._stubs["list_conversations"] + @property + def answer_query( + self, + ) -> Callable[ + [conversational_search_service.AnswerQueryRequest], + conversational_search_service.AnswerQueryResponse, + ]: + r"""Return a callable for the answer query method over gRPC. + + Answer query method. + + Returns: + Callable[[~.AnswerQueryRequest], + ~.AnswerQueryResponse]: + 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 "answer_query" not in self._stubs: + self._stubs["answer_query"] = self.grpc_channel.unary_unary( + "/google.cloud.discoveryengine.v1beta.ConversationalSearchService/AnswerQuery", + request_serializer=conversational_search_service.AnswerQueryRequest.serialize, + response_deserializer=conversational_search_service.AnswerQueryResponse.deserialize, + ) + return self._stubs["answer_query"] + + @property + def get_answer( + self, + ) -> Callable[[conversational_search_service.GetAnswerRequest], answer.Answer]: + r"""Return a callable for the get answer method over gRPC. + + Gets a Answer. + + Returns: + Callable[[~.GetAnswerRequest], + ~.Answer]: + 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_answer" not in self._stubs: + self._stubs["get_answer"] = self.grpc_channel.unary_unary( + "/google.cloud.discoveryengine.v1beta.ConversationalSearchService/GetAnswer", + request_serializer=conversational_search_service.GetAnswerRequest.serialize, + response_deserializer=answer.Answer.deserialize, + ) + return self._stubs["get_answer"] + + @property + def create_session( + self, + ) -> Callable[ + [conversational_search_service.CreateSessionRequest], gcd_session.Session + ]: + r"""Return a callable for the create session method over gRPC. + + Creates a Session. + + If the [Session][google.cloud.discoveryengine.v1beta.Session] to + create already exists, an ALREADY_EXISTS error is returned. + + Returns: + Callable[[~.CreateSessionRequest], + ~.Session]: + 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 "create_session" not in self._stubs: + self._stubs["create_session"] = self.grpc_channel.unary_unary( + "/google.cloud.discoveryengine.v1beta.ConversationalSearchService/CreateSession", + request_serializer=conversational_search_service.CreateSessionRequest.serialize, + response_deserializer=gcd_session.Session.deserialize, + ) + return self._stubs["create_session"] + + @property + def delete_session( + self, + ) -> Callable[ + [conversational_search_service.DeleteSessionRequest], empty_pb2.Empty + ]: + r"""Return a callable for the delete session method over gRPC. + + Deletes a Session. + + If the [Session][google.cloud.discoveryengine.v1beta.Session] to + delete does not exist, a NOT_FOUND error is returned. + + Returns: + Callable[[~.DeleteSessionRequest], + ~.Empty]: + 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 "delete_session" not in self._stubs: + self._stubs["delete_session"] = self.grpc_channel.unary_unary( + "/google.cloud.discoveryengine.v1beta.ConversationalSearchService/DeleteSession", + request_serializer=conversational_search_service.DeleteSessionRequest.serialize, + response_deserializer=empty_pb2.Empty.FromString, + ) + return self._stubs["delete_session"] + + @property + def update_session( + self, + ) -> Callable[ + [conversational_search_service.UpdateSessionRequest], gcd_session.Session + ]: + r"""Return a callable for the update session method over gRPC. + + Updates a Session. + + [Session][google.cloud.discoveryengine.v1beta.Session] action + type cannot be changed. If the + [Session][google.cloud.discoveryengine.v1beta.Session] to update + does not exist, a NOT_FOUND error is returned. + + Returns: + Callable[[~.UpdateSessionRequest], + ~.Session]: + 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_session" not in self._stubs: + self._stubs["update_session"] = self.grpc_channel.unary_unary( + "/google.cloud.discoveryengine.v1beta.ConversationalSearchService/UpdateSession", + request_serializer=conversational_search_service.UpdateSessionRequest.serialize, + response_deserializer=gcd_session.Session.deserialize, + ) + return self._stubs["update_session"] + + @property + def get_session( + self, + ) -> Callable[[conversational_search_service.GetSessionRequest], session.Session]: + r"""Return a callable for the get session method over gRPC. + + Gets a Session. + + Returns: + Callable[[~.GetSessionRequest], + ~.Session]: + 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_session" not in self._stubs: + self._stubs["get_session"] = self.grpc_channel.unary_unary( + "/google.cloud.discoveryengine.v1beta.ConversationalSearchService/GetSession", + request_serializer=conversational_search_service.GetSessionRequest.serialize, + response_deserializer=session.Session.deserialize, + ) + return self._stubs["get_session"] + + @property + def list_sessions( + self, + ) -> Callable[ + [conversational_search_service.ListSessionsRequest], + conversational_search_service.ListSessionsResponse, + ]: + r"""Return a callable for the list sessions method over gRPC. + + Lists all Sessions by their parent + [DataStore][google.cloud.discoveryengine.v1beta.DataStore]. + + Returns: + Callable[[~.ListSessionsRequest], + ~.ListSessionsResponse]: + 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_sessions" not in self._stubs: + self._stubs["list_sessions"] = self.grpc_channel.unary_unary( + "/google.cloud.discoveryengine.v1beta.ConversationalSearchService/ListSessions", + request_serializer=conversational_search_service.ListSessionsRequest.serialize, + response_deserializer=conversational_search_service.ListSessionsResponse.deserialize, + ) + return self._stubs["list_sessions"] + def close(self): self.grpc_channel.close() diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/conversational_search_service/transports/grpc_asyncio.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/conversational_search_service/transports/grpc_asyncio.py index 33e6b22dddc5..d93e05b90bb6 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/conversational_search_service/transports/grpc_asyncio.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/conversational_search_service/transports/grpc_asyncio.py @@ -27,7 +27,10 @@ from google.cloud.discoveryengine_v1beta.types import conversation as gcd_conversation from google.cloud.discoveryengine_v1beta.types import conversational_search_service +from google.cloud.discoveryengine_v1beta.types import answer from google.cloud.discoveryengine_v1beta.types import conversation +from google.cloud.discoveryengine_v1beta.types import session +from google.cloud.discoveryengine_v1beta.types import session as gcd_session from .base import DEFAULT_CLIENT_INFO, ConversationalSearchServiceTransport from .grpc import ConversationalSearchServiceGrpcTransport @@ -426,6 +429,218 @@ def list_conversations( ) return self._stubs["list_conversations"] + @property + def answer_query( + self, + ) -> Callable[ + [conversational_search_service.AnswerQueryRequest], + Awaitable[conversational_search_service.AnswerQueryResponse], + ]: + r"""Return a callable for the answer query method over gRPC. + + Answer query method. + + Returns: + Callable[[~.AnswerQueryRequest], + Awaitable[~.AnswerQueryResponse]]: + 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 "answer_query" not in self._stubs: + self._stubs["answer_query"] = self.grpc_channel.unary_unary( + "/google.cloud.discoveryengine.v1beta.ConversationalSearchService/AnswerQuery", + request_serializer=conversational_search_service.AnswerQueryRequest.serialize, + response_deserializer=conversational_search_service.AnswerQueryResponse.deserialize, + ) + return self._stubs["answer_query"] + + @property + def get_answer( + self, + ) -> Callable[ + [conversational_search_service.GetAnswerRequest], Awaitable[answer.Answer] + ]: + r"""Return a callable for the get answer method over gRPC. + + Gets a Answer. + + Returns: + Callable[[~.GetAnswerRequest], + Awaitable[~.Answer]]: + 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_answer" not in self._stubs: + self._stubs["get_answer"] = self.grpc_channel.unary_unary( + "/google.cloud.discoveryengine.v1beta.ConversationalSearchService/GetAnswer", + request_serializer=conversational_search_service.GetAnswerRequest.serialize, + response_deserializer=answer.Answer.deserialize, + ) + return self._stubs["get_answer"] + + @property + def create_session( + self, + ) -> Callable[ + [conversational_search_service.CreateSessionRequest], + Awaitable[gcd_session.Session], + ]: + r"""Return a callable for the create session method over gRPC. + + Creates a Session. + + If the [Session][google.cloud.discoveryengine.v1beta.Session] to + create already exists, an ALREADY_EXISTS error is returned. + + Returns: + Callable[[~.CreateSessionRequest], + Awaitable[~.Session]]: + 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 "create_session" not in self._stubs: + self._stubs["create_session"] = self.grpc_channel.unary_unary( + "/google.cloud.discoveryengine.v1beta.ConversationalSearchService/CreateSession", + request_serializer=conversational_search_service.CreateSessionRequest.serialize, + response_deserializer=gcd_session.Session.deserialize, + ) + return self._stubs["create_session"] + + @property + def delete_session( + self, + ) -> Callable[ + [conversational_search_service.DeleteSessionRequest], Awaitable[empty_pb2.Empty] + ]: + r"""Return a callable for the delete session method over gRPC. + + Deletes a Session. + + If the [Session][google.cloud.discoveryengine.v1beta.Session] to + delete does not exist, a NOT_FOUND error is returned. + + Returns: + Callable[[~.DeleteSessionRequest], + Awaitable[~.Empty]]: + 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 "delete_session" not in self._stubs: + self._stubs["delete_session"] = self.grpc_channel.unary_unary( + "/google.cloud.discoveryengine.v1beta.ConversationalSearchService/DeleteSession", + request_serializer=conversational_search_service.DeleteSessionRequest.serialize, + response_deserializer=empty_pb2.Empty.FromString, + ) + return self._stubs["delete_session"] + + @property + def update_session( + self, + ) -> Callable[ + [conversational_search_service.UpdateSessionRequest], + Awaitable[gcd_session.Session], + ]: + r"""Return a callable for the update session method over gRPC. + + Updates a Session. + + [Session][google.cloud.discoveryengine.v1beta.Session] action + type cannot be changed. If the + [Session][google.cloud.discoveryengine.v1beta.Session] to update + does not exist, a NOT_FOUND error is returned. + + Returns: + Callable[[~.UpdateSessionRequest], + Awaitable[~.Session]]: + 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_session" not in self._stubs: + self._stubs["update_session"] = self.grpc_channel.unary_unary( + "/google.cloud.discoveryengine.v1beta.ConversationalSearchService/UpdateSession", + request_serializer=conversational_search_service.UpdateSessionRequest.serialize, + response_deserializer=gcd_session.Session.deserialize, + ) + return self._stubs["update_session"] + + @property + def get_session( + self, + ) -> Callable[ + [conversational_search_service.GetSessionRequest], Awaitable[session.Session] + ]: + r"""Return a callable for the get session method over gRPC. + + Gets a Session. + + Returns: + Callable[[~.GetSessionRequest], + Awaitable[~.Session]]: + 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_session" not in self._stubs: + self._stubs["get_session"] = self.grpc_channel.unary_unary( + "/google.cloud.discoveryengine.v1beta.ConversationalSearchService/GetSession", + request_serializer=conversational_search_service.GetSessionRequest.serialize, + response_deserializer=session.Session.deserialize, + ) + return self._stubs["get_session"] + + @property + def list_sessions( + self, + ) -> Callable[ + [conversational_search_service.ListSessionsRequest], + Awaitable[conversational_search_service.ListSessionsResponse], + ]: + r"""Return a callable for the list sessions method over gRPC. + + Lists all Sessions by their parent + [DataStore][google.cloud.discoveryengine.v1beta.DataStore]. + + Returns: + Callable[[~.ListSessionsRequest], + Awaitable[~.ListSessionsResponse]]: + 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_sessions" not in self._stubs: + self._stubs["list_sessions"] = self.grpc_channel.unary_unary( + "/google.cloud.discoveryengine.v1beta.ConversationalSearchService/ListSessions", + request_serializer=conversational_search_service.ListSessionsRequest.serialize, + response_deserializer=conversational_search_service.ListSessionsResponse.deserialize, + ) + return self._stubs["list_sessions"] + def close(self): return self.grpc_channel.close() diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/conversational_search_service/transports/rest.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/conversational_search_service/transports/rest.py index 33a04e1d3ce1..22ac99a2bd12 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/conversational_search_service/transports/rest.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/conversational_search_service/transports/rest.py @@ -42,7 +42,10 @@ from google.cloud.discoveryengine_v1beta.types import conversation as gcd_conversation from google.cloud.discoveryengine_v1beta.types import conversational_search_service +from google.cloud.discoveryengine_v1beta.types import answer from google.cloud.discoveryengine_v1beta.types import conversation +from google.cloud.discoveryengine_v1beta.types import session +from google.cloud.discoveryengine_v1beta.types import session as gcd_session from .base import ConversationalSearchServiceTransport from .base import DEFAULT_CLIENT_INFO as BASE_DEFAULT_CLIENT_INFO @@ -69,6 +72,14 @@ class ConversationalSearchServiceRestInterceptor: .. code-block:: python class MyCustomConversationalSearchServiceInterceptor(ConversationalSearchServiceRestInterceptor): + def pre_answer_query(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_answer_query(self, response): + logging.log(f"Received response: {response}") + return response + def pre_converse_conversation(self, request, metadata): logging.log(f"Received request: {request}") return request, metadata @@ -85,10 +96,30 @@ def post_create_conversation(self, response): logging.log(f"Received response: {response}") return response + def pre_create_session(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_create_session(self, response): + logging.log(f"Received response: {response}") + return response + def pre_delete_conversation(self, request, metadata): logging.log(f"Received request: {request}") return request, metadata + def pre_delete_session(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def pre_get_answer(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_get_answer(self, response): + logging.log(f"Received response: {response}") + return response + def pre_get_conversation(self, request, metadata): logging.log(f"Received request: {request}") return request, metadata @@ -97,6 +128,14 @@ def post_get_conversation(self, response): logging.log(f"Received response: {response}") return response + def pre_get_session(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_get_session(self, response): + logging.log(f"Received response: {response}") + return response + def pre_list_conversations(self, request, metadata): logging.log(f"Received request: {request}") return request, metadata @@ -105,6 +144,14 @@ def post_list_conversations(self, response): logging.log(f"Received response: {response}") return response + def pre_list_sessions(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_list_sessions(self, response): + logging.log(f"Received response: {response}") + return response + def pre_update_conversation(self, request, metadata): logging.log(f"Received request: {request}") return request, metadata @@ -113,12 +160,45 @@ def post_update_conversation(self, response): logging.log(f"Received response: {response}") return response + def pre_update_session(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_update_session(self, response): + logging.log(f"Received response: {response}") + return response + transport = ConversationalSearchServiceRestTransport(interceptor=MyCustomConversationalSearchServiceInterceptor()) client = ConversationalSearchServiceClient(transport=transport) """ + def pre_answer_query( + self, + request: conversational_search_service.AnswerQueryRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[ + conversational_search_service.AnswerQueryRequest, Sequence[Tuple[str, str]] + ]: + """Pre-rpc interceptor for answer_query + + Override in a subclass to manipulate the request or metadata + before they are sent to the ConversationalSearchService server. + """ + return request, metadata + + def post_answer_query( + self, response: conversational_search_service.AnswerQueryResponse + ) -> conversational_search_service.AnswerQueryResponse: + """Post-rpc interceptor for answer_query + + Override in a subclass to manipulate the response + after it is returned by the ConversationalSearchService server but before + it is returned to user code. + """ + return response + def pre_converse_conversation( self, request: conversational_search_service.ConverseConversationRequest, @@ -171,6 +251,29 @@ def post_create_conversation( """ return response + def pre_create_session( + self, + request: conversational_search_service.CreateSessionRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[ + conversational_search_service.CreateSessionRequest, Sequence[Tuple[str, str]] + ]: + """Pre-rpc interceptor for create_session + + Override in a subclass to manipulate the request or metadata + before they are sent to the ConversationalSearchService server. + """ + return request, metadata + + def post_create_session(self, response: gcd_session.Session) -> gcd_session.Session: + """Post-rpc interceptor for create_session + + Override in a subclass to manipulate the response + after it is returned by the ConversationalSearchService server but before + it is returned to user code. + """ + return response + def pre_delete_conversation( self, request: conversational_search_service.DeleteConversationRequest, @@ -186,6 +289,43 @@ def pre_delete_conversation( """ return request, metadata + def pre_delete_session( + self, + request: conversational_search_service.DeleteSessionRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[ + conversational_search_service.DeleteSessionRequest, Sequence[Tuple[str, str]] + ]: + """Pre-rpc interceptor for delete_session + + Override in a subclass to manipulate the request or metadata + before they are sent to the ConversationalSearchService server. + """ + return request, metadata + + def pre_get_answer( + self, + request: conversational_search_service.GetAnswerRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[ + conversational_search_service.GetAnswerRequest, Sequence[Tuple[str, str]] + ]: + """Pre-rpc interceptor for get_answer + + Override in a subclass to manipulate the request or metadata + before they are sent to the ConversationalSearchService server. + """ + return request, metadata + + def post_get_answer(self, response: answer.Answer) -> answer.Answer: + """Post-rpc interceptor for get_answer + + Override in a subclass to manipulate the response + after it is returned by the ConversationalSearchService server but before + it is returned to user code. + """ + return response + def pre_get_conversation( self, request: conversational_search_service.GetConversationRequest, @@ -211,6 +351,29 @@ def post_get_conversation( """ return response + def pre_get_session( + self, + request: conversational_search_service.GetSessionRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[ + conversational_search_service.GetSessionRequest, Sequence[Tuple[str, str]] + ]: + """Pre-rpc interceptor for get_session + + Override in a subclass to manipulate the request or metadata + before they are sent to the ConversationalSearchService server. + """ + return request, metadata + + def post_get_session(self, response: session.Session) -> session.Session: + """Post-rpc interceptor for get_session + + Override in a subclass to manipulate the response + after it is returned by the ConversationalSearchService server but before + it is returned to user code. + """ + return response + def pre_list_conversations( self, request: conversational_search_service.ListConversationsRequest, @@ -237,6 +400,31 @@ def post_list_conversations( """ return response + def pre_list_sessions( + self, + request: conversational_search_service.ListSessionsRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[ + conversational_search_service.ListSessionsRequest, Sequence[Tuple[str, str]] + ]: + """Pre-rpc interceptor for list_sessions + + Override in a subclass to manipulate the request or metadata + before they are sent to the ConversationalSearchService server. + """ + return request, metadata + + def post_list_sessions( + self, response: conversational_search_service.ListSessionsResponse + ) -> conversational_search_service.ListSessionsResponse: + """Post-rpc interceptor for list_sessions + + Override in a subclass to manipulate the response + after it is returned by the ConversationalSearchService server but before + it is returned to user code. + """ + return response + def pre_update_conversation( self, request: conversational_search_service.UpdateConversationRequest, @@ -263,6 +451,29 @@ def post_update_conversation( """ return response + def pre_update_session( + self, + request: conversational_search_service.UpdateSessionRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[ + conversational_search_service.UpdateSessionRequest, Sequence[Tuple[str, str]] + ]: + """Pre-rpc interceptor for update_session + + Override in a subclass to manipulate the request or metadata + before they are sent to the ConversationalSearchService server. + """ + return request, metadata + + def post_update_session(self, response: gcd_session.Session) -> gcd_session.Session: + """Post-rpc interceptor for update_session + + Override in a subclass to manipulate the response + after it is returned by the ConversationalSearchService server but before + it is returned to user code. + """ + return response + def pre_get_operation( self, request: operations_pb2.GetOperationRequest, @@ -406,6 +617,113 @@ def __init__( self._interceptor = interceptor or ConversationalSearchServiceRestInterceptor() self._prep_wrapped_messages(client_info) + class _AnswerQuery(ConversationalSearchServiceRestStub): + def __hash__(self): + return hash("AnswerQuery") + + __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: conversational_search_service.AnswerQueryRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> conversational_search_service.AnswerQueryResponse: + r"""Call the answer query method over HTTP. + + Args: + request (~.conversational_search_service.AnswerQueryRequest): + The request object. Request message for + [ConversationalSearchService.AnswerQuery][google.cloud.discoveryengine.v1beta.ConversationalSearchService.AnswerQuery] + 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: + ~.conversational_search_service.AnswerQueryResponse: + Response message for + [ConversationalSearchService.AnswerQuery][google.cloud.discoveryengine.v1beta.ConversationalSearchService.AnswerQuery] + method. + + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "post", + "uri": "/v1beta/{serving_config=projects/*/locations/*/dataStores/*/servingConfigs/*}:answer", + "body": "*", + }, + { + "method": "post", + "uri": "/v1beta/{serving_config=projects/*/locations/*/collections/*/dataStores/*/servingConfigs/*}:answer", + "body": "*", + }, + { + "method": "post", + "uri": "/v1beta/{serving_config=projects/*/locations/*/collections/*/engines/*/servingConfigs/*}:answer", + "body": "*", + }, + ] + request, metadata = self._interceptor.pre_answer_query(request, metadata) + pb_request = conversational_search_service.AnswerQueryRequest.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 = conversational_search_service.AnswerQueryResponse() + pb_resp = conversational_search_service.AnswerQueryResponse.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + resp = self._interceptor.post_answer_query(resp) + return resp + class _ConverseConversation(ConversationalSearchServiceRestStub): def __hash__(self): return hash("ConverseConversation") @@ -628,9 +946,9 @@ def __call__( resp = self._interceptor.post_create_conversation(resp) return resp - class _DeleteConversation(ConversationalSearchServiceRestStub): + class _CreateSession(ConversationalSearchServiceRestStub): def __hash__(self): - return hash("DeleteConversation") + return hash("CreateSession") __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} @@ -644,43 +962,410 @@ def _get_unset_required_fields(cls, message_dict): def __call__( self, - request: conversational_search_service.DeleteConversationRequest, + request: conversational_search_service.CreateSessionRequest, *, retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: Optional[float] = None, metadata: Sequence[Tuple[str, str]] = (), - ): - r"""Call the delete conversation method over HTTP. + ) -> gcd_session.Session: + r"""Call the create session method over HTTP. Args: - request (~.conversational_search_service.DeleteConversationRequest): - The request object. Request for DeleteConversation - method. + request (~.conversational_search_service.CreateSessionRequest): + The request object. Request for CreateSession 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: + ~.gcd_session.Session: + External session proto definition. """ http_options: List[Dict[str, str]] = [ { - "method": "delete", - "uri": "/v1beta/{name=projects/*/locations/*/dataStores/*/conversations/*}", + "method": "post", + "uri": "/v1beta/{parent=projects/*/locations/*/dataStores/*}/sessions", + "body": "session", }, { - "method": "delete", - "uri": "/v1beta/{name=projects/*/locations/*/collections/*/dataStores/*/conversations/*}", + "method": "post", + "uri": "/v1beta/{parent=projects/*/locations/*/collections/*/dataStores/*}/sessions", + "body": "session", + }, + { + "method": "post", + "uri": "/v1beta/{parent=projects/*/locations/*/collections/*/engines/*}/sessions", + "body": "session", + }, + ] + request, metadata = self._interceptor.pre_create_session(request, metadata) + pb_request = conversational_search_service.CreateSessionRequest.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 = gcd_session.Session() + pb_resp = gcd_session.Session.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + resp = self._interceptor.post_create_session(resp) + return resp + + class _DeleteConversation(ConversationalSearchServiceRestStub): + def __hash__(self): + return hash("DeleteConversation") + + __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: conversational_search_service.DeleteConversationRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ): + r"""Call the delete conversation method over HTTP. + + Args: + request (~.conversational_search_service.DeleteConversationRequest): + The request object. Request for DeleteConversation + 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. + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "delete", + "uri": "/v1beta/{name=projects/*/locations/*/dataStores/*/conversations/*}", + }, + { + "method": "delete", + "uri": "/v1beta/{name=projects/*/locations/*/collections/*/dataStores/*/conversations/*}", + }, + { + "method": "delete", + "uri": "/v1beta/{name=projects/*/locations/*/collections/*/engines/*/conversations/*}", + }, + ] + request, metadata = self._interceptor.pre_delete_conversation( + request, metadata + ) + pb_request = conversational_search_service.DeleteConversationRequest.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) + + class _DeleteSession(ConversationalSearchServiceRestStub): + def __hash__(self): + return hash("DeleteSession") + + __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: conversational_search_service.DeleteSessionRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ): + r"""Call the delete session method over HTTP. + + Args: + request (~.conversational_search_service.DeleteSessionRequest): + The request object. Request for DeleteSession 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. + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "delete", + "uri": "/v1beta/{name=projects/*/locations/*/dataStores/*/sessions/*}", + }, + { + "method": "delete", + "uri": "/v1beta/{name=projects/*/locations/*/collections/*/dataStores/*/sessions/*}", + }, + { + "method": "delete", + "uri": "/v1beta/{name=projects/*/locations/*/collections/*/engines/*/sessions/*}", + }, + ] + request, metadata = self._interceptor.pre_delete_session(request, metadata) + pb_request = conversational_search_service.DeleteSessionRequest.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) + + class _GetAnswer(ConversationalSearchServiceRestStub): + def __hash__(self): + return hash("GetAnswer") + + __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: conversational_search_service.GetAnswerRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> answer.Answer: + r"""Call the get answer method over HTTP. + + Args: + request (~.conversational_search_service.GetAnswerRequest): + The request object. Request for GetAnswer 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: + ~.answer.Answer: + Defines an answer. + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/dataStores/*/sessions/*/answers/*}", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/collections/*/dataStores/*/sessions/*/answers/*}", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/collections/*/engines/*/sessions/*/answers/*}", + }, + ] + request, metadata = self._interceptor.pre_get_answer(request, metadata) + pb_request = conversational_search_service.GetAnswerRequest.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 = answer.Answer() + pb_resp = answer.Answer.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + resp = self._interceptor.post_get_answer(resp) + return resp + + class _GetConversation(ConversationalSearchServiceRestStub): + def __hash__(self): + return hash("GetConversation") + + __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: conversational_search_service.GetConversationRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> conversation.Conversation: + r"""Call the get conversation method over HTTP. + + Args: + request (~.conversational_search_service.GetConversationRequest): + The request object. Request for GetConversation 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: + ~.conversation.Conversation: + External conversation proto + definition. + + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/dataStores/*/conversations/*}", }, { - "method": "delete", + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/collections/*/dataStores/*/conversations/*}", + }, + { + "method": "get", "uri": "/v1beta/{name=projects/*/locations/*/collections/*/engines/*/conversations/*}", }, ] - request, metadata = self._interceptor.pre_delete_conversation( + request, metadata = self._interceptor.pre_get_conversation( request, metadata ) - pb_request = conversational_search_service.DeleteConversationRequest.pb( + pb_request = conversational_search_service.GetConversationRequest.pb( request ) transcoded_request = path_template.transcode(http_options, pb_request) @@ -714,9 +1399,17 @@ def __call__( if response.status_code >= 400: raise core_exceptions.from_http_response(response) - class _GetConversation(ConversationalSearchServiceRestStub): + # Return the response + resp = conversation.Conversation() + pb_resp = conversation.Conversation.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + resp = self._interceptor.post_get_conversation(resp) + return resp + + class _GetSession(ConversationalSearchServiceRestStub): def __hash__(self): - return hash("GetConversation") + return hash("GetSession") __REQUIRED_FIELDS_DEFAULT_VALUES: Dict[str, Any] = {} @@ -730,17 +1423,17 @@ def _get_unset_required_fields(cls, message_dict): def __call__( self, - request: conversational_search_service.GetConversationRequest, + request: conversational_search_service.GetSessionRequest, *, retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: Optional[float] = None, metadata: Sequence[Tuple[str, str]] = (), - ) -> conversation.Conversation: - r"""Call the get conversation method over HTTP. + ) -> session.Session: + r"""Call the get session method over HTTP. Args: - request (~.conversational_search_service.GetConversationRequest): - The request object. Request for GetConversation method. + request (~.conversational_search_service.GetSessionRequest): + The request object. Request for GetSession method. retry (google.api_core.retry.Retry): Designation of what errors, if any, should be retried. timeout (float): The timeout for this request. @@ -748,32 +1441,26 @@ def __call__( sent along with the request as metadata. Returns: - ~.conversation.Conversation: - External conversation proto - definition. - + ~.session.Session: + External session proto definition. """ http_options: List[Dict[str, str]] = [ { "method": "get", - "uri": "/v1beta/{name=projects/*/locations/*/dataStores/*/conversations/*}", + "uri": "/v1beta/{name=projects/*/locations/*/dataStores/*/sessions/*}", }, { "method": "get", - "uri": "/v1beta/{name=projects/*/locations/*/collections/*/dataStores/*/conversations/*}", + "uri": "/v1beta/{name=projects/*/locations/*/collections/*/dataStores/*/sessions/*}", }, { "method": "get", - "uri": "/v1beta/{name=projects/*/locations/*/collections/*/engines/*/conversations/*}", + "uri": "/v1beta/{name=projects/*/locations/*/collections/*/engines/*/sessions/*}", }, ] - request, metadata = self._interceptor.pre_get_conversation( - request, metadata - ) - pb_request = conversational_search_service.GetConversationRequest.pb( - request - ) + request, metadata = self._interceptor.pre_get_session(request, metadata) + pb_request = conversational_search_service.GetSessionRequest.pb(request) transcoded_request = path_template.transcode(http_options, pb_request) uri = transcoded_request["uri"] @@ -806,11 +1493,11 @@ def __call__( raise core_exceptions.from_http_response(response) # Return the response - resp = conversation.Conversation() - pb_resp = conversation.Conversation.pb(resp) + resp = session.Session() + pb_resp = session.Session.pb(resp) json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) - resp = self._interceptor.post_get_conversation(resp) + resp = self._interceptor.post_get_session(resp) return resp class _ListConversations(ConversationalSearchServiceRestStub): @@ -912,6 +1599,99 @@ def __call__( resp = self._interceptor.post_list_conversations(resp) return resp + class _ListSessions(ConversationalSearchServiceRestStub): + def __hash__(self): + return hash("ListSessions") + + __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: conversational_search_service.ListSessionsRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> conversational_search_service.ListSessionsResponse: + r"""Call the list sessions method over HTTP. + + Args: + request (~.conversational_search_service.ListSessionsRequest): + The request object. Request for ListSessions 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: + ~.conversational_search_service.ListSessionsResponse: + Response for ListSessions method. + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "get", + "uri": "/v1beta/{parent=projects/*/locations/*/dataStores/*}/sessions", + }, + { + "method": "get", + "uri": "/v1beta/{parent=projects/*/locations/*/collections/*/dataStores/*}/sessions", + }, + { + "method": "get", + "uri": "/v1beta/{parent=projects/*/locations/*/collections/*/engines/*}/sessions", + }, + ] + request, metadata = self._interceptor.pre_list_sessions(request, metadata) + pb_request = conversational_search_service.ListSessionsRequest.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 = conversational_search_service.ListSessionsResponse() + pb_resp = conversational_search_service.ListSessionsResponse.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + resp = self._interceptor.post_list_sessions(resp) + return resp + class _UpdateConversation(ConversationalSearchServiceRestStub): def __hash__(self): return hash("UpdateConversation") @@ -1021,6 +1801,119 @@ def __call__( resp = self._interceptor.post_update_conversation(resp) return resp + class _UpdateSession(ConversationalSearchServiceRestStub): + def __hash__(self): + return hash("UpdateSession") + + __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: conversational_search_service.UpdateSessionRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> gcd_session.Session: + r"""Call the update session method over HTTP. + + Args: + request (~.conversational_search_service.UpdateSessionRequest): + The request object. Request for UpdateSession 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: + ~.gcd_session.Session: + External session proto definition. + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "patch", + "uri": "/v1beta/{session.name=projects/*/locations/*/dataStores/*/sessions/*}", + "body": "session", + }, + { + "method": "patch", + "uri": "/v1beta/{session.name=projects/*/locations/*/collections/*/dataStores/*/sessions/*}", + "body": "session", + }, + { + "method": "patch", + "uri": "/v1beta/{session.name=projects/*/locations/*/collections/*/engines/*/sessions/*}", + "body": "session", + }, + ] + request, metadata = self._interceptor.pre_update_session(request, metadata) + pb_request = conversational_search_service.UpdateSessionRequest.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 = gcd_session.Session() + pb_resp = gcd_session.Session.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + resp = self._interceptor.post_update_session(resp) + return resp + + @property + def answer_query( + self, + ) -> Callable[ + [conversational_search_service.AnswerQueryRequest], + conversational_search_service.AnswerQueryResponse, + ]: + # 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._AnswerQuery(self._session, self._host, self._interceptor) # type: ignore + @property def converse_conversation( self, @@ -1043,6 +1936,16 @@ def create_conversation( # In C++ this would require a dynamic_cast return self._CreateConversation(self._session, self._host, self._interceptor) # type: ignore + @property + def create_session( + self, + ) -> Callable[ + [conversational_search_service.CreateSessionRequest], gcd_session.Session + ]: + # 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._CreateSession(self._session, self._host, self._interceptor) # type: ignore + @property def delete_conversation( self, @@ -1053,6 +1956,24 @@ def delete_conversation( # In C++ this would require a dynamic_cast return self._DeleteConversation(self._session, self._host, self._interceptor) # type: ignore + @property + def delete_session( + self, + ) -> Callable[ + [conversational_search_service.DeleteSessionRequest], empty_pb2.Empty + ]: + # 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._DeleteSession(self._session, self._host, self._interceptor) # type: ignore + + @property + def get_answer( + self, + ) -> Callable[[conversational_search_service.GetAnswerRequest], answer.Answer]: + # 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._GetAnswer(self._session, self._host, self._interceptor) # type: ignore + @property def get_conversation( self, @@ -1064,6 +1985,14 @@ def get_conversation( # In C++ this would require a dynamic_cast return self._GetConversation(self._session, self._host, self._interceptor) # type: ignore + @property + def get_session( + self, + ) -> Callable[[conversational_search_service.GetSessionRequest], session.Session]: + # 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._GetSession(self._session, self._host, self._interceptor) # type: ignore + @property def list_conversations( self, @@ -1075,6 +2004,17 @@ def list_conversations( # In C++ this would require a dynamic_cast return self._ListConversations(self._session, self._host, self._interceptor) # type: ignore + @property + def list_sessions( + self, + ) -> Callable[ + [conversational_search_service.ListSessionsRequest], + conversational_search_service.ListSessionsResponse, + ]: + # 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._ListSessions(self._session, self._host, self._interceptor) # type: ignore + @property def update_conversation( self, @@ -1086,6 +2026,16 @@ def update_conversation( # In C++ this would require a dynamic_cast return self._UpdateConversation(self._session, self._host, self._interceptor) # type: ignore + @property + def update_session( + self, + ) -> Callable[ + [conversational_search_service.UpdateSessionRequest], gcd_session.Session + ]: + # 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._UpdateSession(self._session, self._host, self._interceptor) # type: ignore + @property def get_operation(self): return self._GetOperation(self._session, self._host, self._interceptor) # type: ignore diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/document_service/async_client.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/document_service/async_client.py index 254c42bde95e..14ffc6dce7ee 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/document_service/async_client.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/document_service/async_client.py @@ -46,6 +46,7 @@ from google.api_core import operation_async # 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.protobuf import struct_pb2 # type: ignore from google.protobuf import timestamp_pb2 # type: ignore @@ -82,6 +83,8 @@ class DocumentServiceAsyncClient: parse_branch_path = staticmethod(DocumentServiceClient.parse_branch_path) document_path = staticmethod(DocumentServiceClient.document_path) parse_document_path = staticmethod(DocumentServiceClient.parse_document_path) + fhir_store_path = staticmethod(DocumentServiceClient.fhir_store_path) + parse_fhir_store_path = staticmethod(DocumentServiceClient.parse_fhir_store_path) common_billing_account_path = staticmethod( DocumentServiceClient.common_billing_account_path ) @@ -669,10 +672,12 @@ async def update_document( self, request: Optional[Union[document_service.UpdateDocumentRequest, dict]] = None, *, + document: Optional[gcd_document.Document] = 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]] = (), - ) -> document.Document: + ) -> gcd_document.Document: r"""Updates a [Document][google.cloud.discoveryengine.v1beta.Document]. @@ -706,6 +711,32 @@ async def sample_update_document(): The request object. Request message for [DocumentService.UpdateDocument][google.cloud.discoveryengine.v1beta.DocumentService.UpdateDocument] method. + document (:class:`google.cloud.discoveryengine_v1beta.types.Document`): + Required. The document to update/create. + + If the caller does not have permission to update the + [Document][google.cloud.discoveryengine.v1beta.Document], + regardless of whether or not it exists, a + ``PERMISSION_DENIED`` error is returned. + + If the + [Document][google.cloud.discoveryengine.v1beta.Document] + to update does not exist and + [allow_missing][google.cloud.discoveryengine.v1beta.UpdateDocumentRequest.allow_missing] + is not set, a ``NOT_FOUND`` error is returned. + + This corresponds to the ``document`` 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 imported 'document' to update. + If not set, will by default update all + fields. + + 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. @@ -720,8 +751,24 @@ async def sample_update_document(): """ # 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([document, 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." + ) + request = document_service.UpdateDocumentRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if document is not None: + request.document = document + 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 = gapic_v1.method_async.wrap_method( diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/document_service/client.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/document_service/client.py index 70de9f90b55e..b453dd2d5a1b 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/document_service/client.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/document_service/client.py @@ -51,6 +51,7 @@ from google.api_core import operation_async # 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.protobuf import struct_pb2 # type: ignore from google.protobuf import timestamp_pb2 # type: ignore @@ -248,6 +249,30 @@ def parse_document_path(path: str) -> Dict[str, str]: ) return m.groupdict() if m else {} + @staticmethod + def fhir_store_path( + project: str, + location: str, + dataset: str, + fhir_store: str, + ) -> str: + """Returns a fully-qualified fhir_store string.""" + return "projects/{project}/locations/{location}/datasets/{dataset}/fhirStores/{fhir_store}".format( + project=project, + location=location, + dataset=dataset, + fhir_store=fhir_store, + ) + + @staticmethod + def parse_fhir_store_path(path: str) -> Dict[str, str]: + """Parses a fhir_store path into its component segments.""" + m = re.match( + r"^projects/(?P.+?)/locations/(?P.+?)/datasets/(?P.+?)/fhirStores/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + @staticmethod def common_billing_account_path( billing_account: str, @@ -1108,10 +1133,12 @@ def update_document( self, request: Optional[Union[document_service.UpdateDocumentRequest, dict]] = None, *, + document: Optional[gcd_document.Document] = 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]] = (), - ) -> document.Document: + ) -> gcd_document.Document: r"""Updates a [Document][google.cloud.discoveryengine.v1beta.Document]. @@ -1145,6 +1172,32 @@ def sample_update_document(): The request object. Request message for [DocumentService.UpdateDocument][google.cloud.discoveryengine.v1beta.DocumentService.UpdateDocument] method. + document (google.cloud.discoveryengine_v1beta.types.Document): + Required. The document to update/create. + + If the caller does not have permission to update the + [Document][google.cloud.discoveryengine.v1beta.Document], + regardless of whether or not it exists, a + ``PERMISSION_DENIED`` error is returned. + + If the + [Document][google.cloud.discoveryengine.v1beta.Document] + to update does not exist and + [allow_missing][google.cloud.discoveryengine.v1beta.UpdateDocumentRequest.allow_missing] + is not set, a ``NOT_FOUND`` error is returned. + + This corresponds to the ``document`` 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 imported 'document' to update. + If not set, will by default update all + fields. + + 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. @@ -1159,12 +1212,27 @@ def sample_update_document(): """ # 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([document, 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." + ) + # Minor optimization to avoid making a copy if the user passes # in a document_service.UpdateDocumentRequest. # There's no risk of modifying the input as we've already verified # there are no flattened fields. if not isinstance(request, document_service.UpdateDocumentRequest): request = document_service.UpdateDocumentRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if document is not None: + request.document = document + 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. diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/document_service/transports/base.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/document_service/transports/base.py index 1b3480390fd4..40352ee68bae 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/document_service/transports/base.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/document_service/transports/base.py @@ -230,7 +230,7 @@ def update_document( self, ) -> Callable[ [document_service.UpdateDocumentRequest], - Union[document.Document, Awaitable[document.Document]], + Union[gcd_document.Document, Awaitable[gcd_document.Document]], ]: raise NotImplementedError() diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/document_service/transports/grpc.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/document_service/transports/grpc.py index 2e1f7c17fcba..a7e63931241b 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/document_service/transports/grpc.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/document_service/transports/grpc.py @@ -339,7 +339,7 @@ def create_document( @property def update_document( self, - ) -> Callable[[document_service.UpdateDocumentRequest], document.Document]: + ) -> Callable[[document_service.UpdateDocumentRequest], gcd_document.Document]: r"""Return a callable for the update document method over gRPC. Updates a @@ -359,7 +359,7 @@ def update_document( self._stubs["update_document"] = self.grpc_channel.unary_unary( "/google.cloud.discoveryengine.v1beta.DocumentService/UpdateDocument", request_serializer=document_service.UpdateDocumentRequest.serialize, - response_deserializer=document.Document.deserialize, + response_deserializer=gcd_document.Document.deserialize, ) return self._stubs["update_document"] diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/document_service/transports/grpc_asyncio.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/document_service/transports/grpc_asyncio.py index 9b5b9512b9af..dc2fb1ab7349 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/document_service/transports/grpc_asyncio.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/document_service/transports/grpc_asyncio.py @@ -348,7 +348,7 @@ def create_document( def update_document( self, ) -> Callable[ - [document_service.UpdateDocumentRequest], Awaitable[document.Document] + [document_service.UpdateDocumentRequest], Awaitable[gcd_document.Document] ]: r"""Return a callable for the update document method over gRPC. @@ -369,7 +369,7 @@ def update_document( self._stubs["update_document"] = self.grpc_channel.unary_unary( "/google.cloud.discoveryengine.v1beta.DocumentService/UpdateDocument", request_serializer=document_service.UpdateDocumentRequest.serialize, - response_deserializer=document.Document.deserialize, + response_deserializer=gcd_document.Document.deserialize, ) return self._stubs["update_document"] diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/document_service/transports/rest.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/document_service/transports/rest.py index 4ffe1570098c..b4a44db777f1 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/document_service/transports/rest.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/document_service/transports/rest.py @@ -274,7 +274,9 @@ def pre_update_document( """ return request, metadata - def post_update_document(self, response: document.Document) -> document.Document: + def post_update_document( + self, response: gcd_document.Document + ) -> gcd_document.Document: """Post-rpc interceptor for update_document Override in a subclass to manipulate the response @@ -1165,7 +1167,7 @@ def __call__( retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: Optional[float] = None, metadata: Sequence[Tuple[str, str]] = (), - ) -> document.Document: + ) -> gcd_document.Document: r"""Call the update document method over HTTP. Args: @@ -1180,7 +1182,7 @@ def __call__( sent along with the request as metadata. Returns: - ~.document.Document: + ~.gcd_document.Document: Document captures all raw metadata information of items to be recommended or searched. @@ -1239,8 +1241,8 @@ def __call__( raise core_exceptions.from_http_response(response) # Return the response - resp = document.Document() - pb_resp = document.Document.pb(resp) + resp = gcd_document.Document() + pb_resp = gcd_document.Document.pb(resp) json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) resp = self._interceptor.post_update_document(resp) @@ -1299,7 +1301,7 @@ def purge_documents( @property def update_document( self, - ) -> Callable[[document_service.UpdateDocumentRequest], document.Document]: + ) -> Callable[[document_service.UpdateDocumentRequest], gcd_document.Document]: # 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._UpdateDocument(self._session, self._host, self._interceptor) # type: ignore diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/engine_service/async_client.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/engine_service/async_client.py index c70222c2c6b7..90ae9e0d8fa5 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/engine_service/async_client.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/engine_service/async_client.py @@ -298,7 +298,7 @@ async def sample_create_engine(): # Initialize request argument(s) engine = discoveryengine_v1beta.Engine() engine.display_name = "display_name_value" - engine.solution_type = "SOLUTION_TYPE_CHAT" + engine.solution_type = "SOLUTION_TYPE_GENERATIVE_CHAT" request = discoveryengine_v1beta.CreateEngineRequest( parent="parent_value", @@ -591,7 +591,7 @@ async def sample_update_engine(): # Initialize request argument(s) engine = discoveryengine_v1beta.Engine() engine.display_name = "display_name_value" - engine.solution_type = "SOLUTION_TYPE_CHAT" + engine.solution_type = "SOLUTION_TYPE_GENERATIVE_CHAT" request = discoveryengine_v1beta.UpdateEngineRequest( engine=engine, @@ -927,6 +927,348 @@ async def sample_list_engines(): # Done; return the response. return response + async def pause_engine( + self, + request: Optional[Union[engine_service.PauseEngineRequest, 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]] = (), + ) -> engine.Engine: + r"""Pauses the training of an existing engine. Only applicable if + [SolutionType][google.cloud.discoveryengine.v1beta.SolutionType] + is + [SOLUTION_TYPE_RECOMMENDATION][google.cloud.discoveryengine.v1beta.SolutionType.SOLUTION_TYPE_RECOMMENDATION]. + + .. 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 discoveryengine_v1beta + + async def sample_pause_engine(): + # Create a client + client = discoveryengine_v1beta.EngineServiceAsyncClient() + + # Initialize request argument(s) + request = discoveryengine_v1beta.PauseEngineRequest( + name="name_value", + ) + + # Make the request + response = await client.pause_engine(request=request) + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.discoveryengine_v1beta.types.PauseEngineRequest, dict]]): + The request object. Request for pausing training of an + engine. + name (:class:`str`): + Required. The name of the engine to pause. Format: + ``projects/{project_number}/locations/{location_id}/collections/{collection_id}/engines/{engine_id}`` + + 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.discoveryengine_v1beta.types.Engine: + Metadata that describes the training and serving parameters of an + [Engine][google.cloud.discoveryengine.v1beta.Engine]. + + """ + # 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." + ) + + request = engine_service.PauseEngineRequest(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 = gapic_v1.method_async.wrap_method( + self._client._transport.pause_engine, + 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 resume_engine( + self, + request: Optional[Union[engine_service.ResumeEngineRequest, 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]] = (), + ) -> engine.Engine: + r"""Resumes the training of an existing engine. Only applicable if + [SolutionType][google.cloud.discoveryengine.v1beta.SolutionType] + is + [SOLUTION_TYPE_RECOMMENDATION][google.cloud.discoveryengine.v1beta.SolutionType.SOLUTION_TYPE_RECOMMENDATION]. + + .. 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 discoveryengine_v1beta + + async def sample_resume_engine(): + # Create a client + client = discoveryengine_v1beta.EngineServiceAsyncClient() + + # Initialize request argument(s) + request = discoveryengine_v1beta.ResumeEngineRequest( + name="name_value", + ) + + # Make the request + response = await client.resume_engine(request=request) + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.discoveryengine_v1beta.types.ResumeEngineRequest, dict]]): + The request object. Request for resuming training of an + engine. + name (:class:`str`): + Required. The name of the engine to resume. Format: + ``projects/{project_number}/locations/{location_id}/collections/{collection_id}/engines/{engine_id}`` + + 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.discoveryengine_v1beta.types.Engine: + Metadata that describes the training and serving parameters of an + [Engine][google.cloud.discoveryengine.v1beta.Engine]. + + """ + # 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." + ) + + request = engine_service.ResumeEngineRequest(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 = gapic_v1.method_async.wrap_method( + self._client._transport.resume_engine, + 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 tune_engine( + self, + request: Optional[Union[engine_service.TuneEngineRequest, 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]] = (), + ) -> operation_async.AsyncOperation: + r"""Tunes an existing engine. Only applicable if + [SolutionType][google.cloud.discoveryengine.v1beta.SolutionType] + is + [SOLUTION_TYPE_RECOMMENDATION][google.cloud.discoveryengine.v1beta.SolutionType.SOLUTION_TYPE_RECOMMENDATION]. + + .. 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 discoveryengine_v1beta + + async def sample_tune_engine(): + # Create a client + client = discoveryengine_v1beta.EngineServiceAsyncClient() + + # Initialize request argument(s) + request = discoveryengine_v1beta.TuneEngineRequest( + name="name_value", + ) + + # Make the request + operation = client.tune_engine(request=request) + + print("Waiting for operation to complete...") + + response = (await operation).result() + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.discoveryengine_v1beta.types.TuneEngineRequest, dict]]): + The request object. Request to manually start a tuning + process now (instead of waiting for the + periodically scheduled tuning to + happen). + name (:class:`str`): + Required. The resource name of the engine to tune. + Format: + ``projects/{project_number}/locations/{location_id}/collections/{collection_id}/engines/{engine_id}`` + + 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.api_core.operation_async.AsyncOperation: + An object representing a long-running operation. + + The result type for the operation will be + :class:`google.cloud.discoveryengine_v1beta.types.TuneEngineResponse` + Response associated with a tune operation. + + """ + # 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." + ) + + request = engine_service.TuneEngineRequest(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 = gapic_v1.method_async.wrap_method( + self._client._transport.tune_engine, + 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, + ) + + # Wrap the response in an operation future. + response = operation_async.from_gapic( + response, + self._client._transport.operations_client, + engine_service.TuneEngineResponse, + metadata_type=engine_service.TuneEngineMetadata, + ) + + # Done; return the response. + return response + async def list_operations( self, request: Optional[operations_pb2.ListOperationsRequest] = None, diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/engine_service/client.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/engine_service/client.py index 81e157441ce0..fb4dee3b445b 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/engine_service/client.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/engine_service/client.py @@ -733,7 +733,7 @@ def sample_create_engine(): # Initialize request argument(s) engine = discoveryengine_v1beta.Engine() engine.display_name = "display_name_value" - engine.solution_type = "SOLUTION_TYPE_CHAT" + engine.solution_type = "SOLUTION_TYPE_GENERATIVE_CHAT" request = discoveryengine_v1beta.CreateEngineRequest( parent="parent_value", @@ -1026,7 +1026,7 @@ def sample_update_engine(): # Initialize request argument(s) engine = discoveryengine_v1beta.Engine() engine.display_name = "display_name_value" - engine.solution_type = "SOLUTION_TYPE_CHAT" + engine.solution_type = "SOLUTION_TYPE_GENERATIVE_CHAT" request = discoveryengine_v1beta.UpdateEngineRequest( engine=engine, @@ -1362,6 +1362,348 @@ def sample_list_engines(): # Done; return the response. return response + def pause_engine( + self, + request: Optional[Union[engine_service.PauseEngineRequest, 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]] = (), + ) -> engine.Engine: + r"""Pauses the training of an existing engine. Only applicable if + [SolutionType][google.cloud.discoveryengine.v1beta.SolutionType] + is + [SOLUTION_TYPE_RECOMMENDATION][google.cloud.discoveryengine.v1beta.SolutionType.SOLUTION_TYPE_RECOMMENDATION]. + + .. 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 discoveryengine_v1beta + + def sample_pause_engine(): + # Create a client + client = discoveryengine_v1beta.EngineServiceClient() + + # Initialize request argument(s) + request = discoveryengine_v1beta.PauseEngineRequest( + name="name_value", + ) + + # Make the request + response = client.pause_engine(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.discoveryengine_v1beta.types.PauseEngineRequest, dict]): + The request object. Request for pausing training of an + engine. + name (str): + Required. The name of the engine to pause. Format: + ``projects/{project_number}/locations/{location_id}/collections/{collection_id}/engines/{engine_id}`` + + 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.discoveryengine_v1beta.types.Engine: + Metadata that describes the training and serving parameters of an + [Engine][google.cloud.discoveryengine.v1beta.Engine]. + + """ + # 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." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a engine_service.PauseEngineRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance(request, engine_service.PauseEngineRequest): + request = engine_service.PauseEngineRequest(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.pause_engine] + + # 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 resume_engine( + self, + request: Optional[Union[engine_service.ResumeEngineRequest, 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]] = (), + ) -> engine.Engine: + r"""Resumes the training of an existing engine. Only applicable if + [SolutionType][google.cloud.discoveryengine.v1beta.SolutionType] + is + [SOLUTION_TYPE_RECOMMENDATION][google.cloud.discoveryengine.v1beta.SolutionType.SOLUTION_TYPE_RECOMMENDATION]. + + .. 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 discoveryengine_v1beta + + def sample_resume_engine(): + # Create a client + client = discoveryengine_v1beta.EngineServiceClient() + + # Initialize request argument(s) + request = discoveryengine_v1beta.ResumeEngineRequest( + name="name_value", + ) + + # Make the request + response = client.resume_engine(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.discoveryengine_v1beta.types.ResumeEngineRequest, dict]): + The request object. Request for resuming training of an + engine. + name (str): + Required. The name of the engine to resume. Format: + ``projects/{project_number}/locations/{location_id}/collections/{collection_id}/engines/{engine_id}`` + + 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.discoveryengine_v1beta.types.Engine: + Metadata that describes the training and serving parameters of an + [Engine][google.cloud.discoveryengine.v1beta.Engine]. + + """ + # 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." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a engine_service.ResumeEngineRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance(request, engine_service.ResumeEngineRequest): + request = engine_service.ResumeEngineRequest(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.resume_engine] + + # 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 tune_engine( + self, + request: Optional[Union[engine_service.TuneEngineRequest, 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]] = (), + ) -> operation.Operation: + r"""Tunes an existing engine. Only applicable if + [SolutionType][google.cloud.discoveryengine.v1beta.SolutionType] + is + [SOLUTION_TYPE_RECOMMENDATION][google.cloud.discoveryengine.v1beta.SolutionType.SOLUTION_TYPE_RECOMMENDATION]. + + .. 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 discoveryengine_v1beta + + def sample_tune_engine(): + # Create a client + client = discoveryengine_v1beta.EngineServiceClient() + + # Initialize request argument(s) + request = discoveryengine_v1beta.TuneEngineRequest( + name="name_value", + ) + + # Make the request + operation = client.tune_engine(request=request) + + print("Waiting for operation to complete...") + + response = operation.result() + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.discoveryengine_v1beta.types.TuneEngineRequest, dict]): + The request object. Request to manually start a tuning + process now (instead of waiting for the + periodically scheduled tuning to + happen). + name (str): + Required. The resource name of the engine to tune. + Format: + ``projects/{project_number}/locations/{location_id}/collections/{collection_id}/engines/{engine_id}`` + + 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.api_core.operation.Operation: + An object representing a long-running operation. + + The result type for the operation will be + :class:`google.cloud.discoveryengine_v1beta.types.TuneEngineResponse` + Response associated with a tune operation. + + """ + # 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." + ) + + # Minor optimization to avoid making a copy if the user passes + # in a engine_service.TuneEngineRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance(request, engine_service.TuneEngineRequest): + request = engine_service.TuneEngineRequest(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.tune_engine] + + # 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, + ) + + # Wrap the response in an operation future. + response = operation.from_gapic( + response, + self._transport.operations_client, + engine_service.TuneEngineResponse, + metadata_type=engine_service.TuneEngineMetadata, + ) + + # Done; return the response. + return response + def __enter__(self) -> "EngineServiceClient": return self diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/engine_service/transports/base.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/engine_service/transports/base.py index a1c4a86fdf64..aa37bb6b9f8d 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/engine_service/transports/base.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/engine_service/transports/base.py @@ -155,6 +155,21 @@ def _prep_wrapped_messages(self, client_info): default_timeout=None, client_info=client_info, ), + self.pause_engine: gapic_v1.method.wrap_method( + self.pause_engine, + default_timeout=None, + client_info=client_info, + ), + self.resume_engine: gapic_v1.method.wrap_method( + self.resume_engine, + default_timeout=None, + client_info=client_info, + ), + self.tune_engine: gapic_v1.method.wrap_method( + self.tune_engine, + default_timeout=None, + client_info=client_info, + ), } def close(self): @@ -219,6 +234,33 @@ def list_engines( ]: raise NotImplementedError() + @property + def pause_engine( + self, + ) -> Callable[ + [engine_service.PauseEngineRequest], + Union[engine.Engine, Awaitable[engine.Engine]], + ]: + raise NotImplementedError() + + @property + def resume_engine( + self, + ) -> Callable[ + [engine_service.ResumeEngineRequest], + Union[engine.Engine, Awaitable[engine.Engine]], + ]: + raise NotImplementedError() + + @property + def tune_engine( + self, + ) -> Callable[ + [engine_service.TuneEngineRequest], + Union[operations_pb2.Operation, Awaitable[operations_pb2.Operation]], + ]: + raise NotImplementedError() + @property def list_operations( self, diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/engine_service/transports/grpc.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/engine_service/transports/grpc.py index 02ca54b13d94..ddcffe577d61 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/engine_service/transports/grpc.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/engine_service/transports/grpc.py @@ -380,6 +380,93 @@ def list_engines( ) return self._stubs["list_engines"] + @property + def pause_engine( + self, + ) -> Callable[[engine_service.PauseEngineRequest], engine.Engine]: + r"""Return a callable for the pause engine method over gRPC. + + Pauses the training of an existing engine. Only applicable if + [SolutionType][google.cloud.discoveryengine.v1beta.SolutionType] + is + [SOLUTION_TYPE_RECOMMENDATION][google.cloud.discoveryengine.v1beta.SolutionType.SOLUTION_TYPE_RECOMMENDATION]. + + Returns: + Callable[[~.PauseEngineRequest], + ~.Engine]: + 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 "pause_engine" not in self._stubs: + self._stubs["pause_engine"] = self.grpc_channel.unary_unary( + "/google.cloud.discoveryengine.v1beta.EngineService/PauseEngine", + request_serializer=engine_service.PauseEngineRequest.serialize, + response_deserializer=engine.Engine.deserialize, + ) + return self._stubs["pause_engine"] + + @property + def resume_engine( + self, + ) -> Callable[[engine_service.ResumeEngineRequest], engine.Engine]: + r"""Return a callable for the resume engine method over gRPC. + + Resumes the training of an existing engine. Only applicable if + [SolutionType][google.cloud.discoveryengine.v1beta.SolutionType] + is + [SOLUTION_TYPE_RECOMMENDATION][google.cloud.discoveryengine.v1beta.SolutionType.SOLUTION_TYPE_RECOMMENDATION]. + + Returns: + Callable[[~.ResumeEngineRequest], + ~.Engine]: + 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 "resume_engine" not in self._stubs: + self._stubs["resume_engine"] = self.grpc_channel.unary_unary( + "/google.cloud.discoveryengine.v1beta.EngineService/ResumeEngine", + request_serializer=engine_service.ResumeEngineRequest.serialize, + response_deserializer=engine.Engine.deserialize, + ) + return self._stubs["resume_engine"] + + @property + def tune_engine( + self, + ) -> Callable[[engine_service.TuneEngineRequest], operations_pb2.Operation]: + r"""Return a callable for the tune engine method over gRPC. + + Tunes an existing engine. Only applicable if + [SolutionType][google.cloud.discoveryengine.v1beta.SolutionType] + is + [SOLUTION_TYPE_RECOMMENDATION][google.cloud.discoveryengine.v1beta.SolutionType.SOLUTION_TYPE_RECOMMENDATION]. + + Returns: + Callable[[~.TuneEngineRequest], + ~.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 "tune_engine" not in self._stubs: + self._stubs["tune_engine"] = self.grpc_channel.unary_unary( + "/google.cloud.discoveryengine.v1beta.EngineService/TuneEngine", + request_serializer=engine_service.TuneEngineRequest.serialize, + response_deserializer=operations_pb2.Operation.FromString, + ) + return self._stubs["tune_engine"] + def close(self): self.grpc_channel.close() diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/engine_service/transports/grpc_asyncio.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/engine_service/transports/grpc_asyncio.py index 98da4ea741c6..b751a1b703d9 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/engine_service/transports/grpc_asyncio.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/engine_service/transports/grpc_asyncio.py @@ -392,6 +392,95 @@ def list_engines( ) return self._stubs["list_engines"] + @property + def pause_engine( + self, + ) -> Callable[[engine_service.PauseEngineRequest], Awaitable[engine.Engine]]: + r"""Return a callable for the pause engine method over gRPC. + + Pauses the training of an existing engine. Only applicable if + [SolutionType][google.cloud.discoveryengine.v1beta.SolutionType] + is + [SOLUTION_TYPE_RECOMMENDATION][google.cloud.discoveryengine.v1beta.SolutionType.SOLUTION_TYPE_RECOMMENDATION]. + + Returns: + Callable[[~.PauseEngineRequest], + Awaitable[~.Engine]]: + 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 "pause_engine" not in self._stubs: + self._stubs["pause_engine"] = self.grpc_channel.unary_unary( + "/google.cloud.discoveryengine.v1beta.EngineService/PauseEngine", + request_serializer=engine_service.PauseEngineRequest.serialize, + response_deserializer=engine.Engine.deserialize, + ) + return self._stubs["pause_engine"] + + @property + def resume_engine( + self, + ) -> Callable[[engine_service.ResumeEngineRequest], Awaitable[engine.Engine]]: + r"""Return a callable for the resume engine method over gRPC. + + Resumes the training of an existing engine. Only applicable if + [SolutionType][google.cloud.discoveryengine.v1beta.SolutionType] + is + [SOLUTION_TYPE_RECOMMENDATION][google.cloud.discoveryengine.v1beta.SolutionType.SOLUTION_TYPE_RECOMMENDATION]. + + Returns: + Callable[[~.ResumeEngineRequest], + Awaitable[~.Engine]]: + 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 "resume_engine" not in self._stubs: + self._stubs["resume_engine"] = self.grpc_channel.unary_unary( + "/google.cloud.discoveryengine.v1beta.EngineService/ResumeEngine", + request_serializer=engine_service.ResumeEngineRequest.serialize, + response_deserializer=engine.Engine.deserialize, + ) + return self._stubs["resume_engine"] + + @property + def tune_engine( + self, + ) -> Callable[ + [engine_service.TuneEngineRequest], Awaitable[operations_pb2.Operation] + ]: + r"""Return a callable for the tune engine method over gRPC. + + Tunes an existing engine. Only applicable if + [SolutionType][google.cloud.discoveryengine.v1beta.SolutionType] + is + [SOLUTION_TYPE_RECOMMENDATION][google.cloud.discoveryengine.v1beta.SolutionType.SOLUTION_TYPE_RECOMMENDATION]. + + Returns: + Callable[[~.TuneEngineRequest], + 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 "tune_engine" not in self._stubs: + self._stubs["tune_engine"] = self.grpc_channel.unary_unary( + "/google.cloud.discoveryengine.v1beta.EngineService/TuneEngine", + request_serializer=engine_service.TuneEngineRequest.serialize, + response_deserializer=operations_pb2.Operation.FromString, + ) + return self._stubs["tune_engine"] + def close(self): return self.grpc_channel.close() diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/engine_service/transports/rest.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/engine_service/transports/rest.py index 416b7e94a6b3..214127a9f05c 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/engine_service/transports/rest.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/engine_service/transports/rest.py @@ -106,6 +106,30 @@ def post_list_engines(self, response): logging.log(f"Received response: {response}") return response + def pre_pause_engine(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_pause_engine(self, response): + logging.log(f"Received response: {response}") + return response + + def pre_resume_engine(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_resume_engine(self, response): + logging.log(f"Received response: {response}") + return response + + def pre_tune_engine(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_tune_engine(self, response): + logging.log(f"Received response: {response}") + return response + def pre_update_engine(self, request, metadata): logging.log(f"Received request: {request}") return request, metadata @@ -210,6 +234,71 @@ def post_list_engines( """ return response + def pre_pause_engine( + self, + request: engine_service.PauseEngineRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[engine_service.PauseEngineRequest, Sequence[Tuple[str, str]]]: + """Pre-rpc interceptor for pause_engine + + Override in a subclass to manipulate the request or metadata + before they are sent to the EngineService server. + """ + return request, metadata + + def post_pause_engine(self, response: engine.Engine) -> engine.Engine: + """Post-rpc interceptor for pause_engine + + Override in a subclass to manipulate the response + after it is returned by the EngineService server but before + it is returned to user code. + """ + return response + + def pre_resume_engine( + self, + request: engine_service.ResumeEngineRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[engine_service.ResumeEngineRequest, Sequence[Tuple[str, str]]]: + """Pre-rpc interceptor for resume_engine + + Override in a subclass to manipulate the request or metadata + before they are sent to the EngineService server. + """ + return request, metadata + + def post_resume_engine(self, response: engine.Engine) -> engine.Engine: + """Post-rpc interceptor for resume_engine + + Override in a subclass to manipulate the response + after it is returned by the EngineService server but before + it is returned to user code. + """ + return response + + def pre_tune_engine( + self, + request: engine_service.TuneEngineRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[engine_service.TuneEngineRequest, Sequence[Tuple[str, str]]]: + """Pre-rpc interceptor for tune_engine + + Override in a subclass to manipulate the request or metadata + before they are sent to the EngineService server. + """ + return request, metadata + + def post_tune_engine( + self, response: operations_pb2.Operation + ) -> operations_pb2.Operation: + """Post-rpc interceptor for tune_engine + + Override in a subclass to manipulate the response + after it is returned by the EngineService server but before + it is returned to user code. + """ + return response + def pre_update_engine( self, request: engine_service.UpdateEngineRequest, @@ -885,6 +974,294 @@ def __call__( resp = self._interceptor.post_list_engines(resp) return resp + class _PauseEngine(EngineServiceRestStub): + def __hash__(self): + return hash("PauseEngine") + + __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: engine_service.PauseEngineRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> engine.Engine: + r"""Call the pause engine method over HTTP. + + Args: + request (~.engine_service.PauseEngineRequest): + The request object. Request for pausing training of an + engine. + 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: + ~.engine.Engine: + Metadata that describes the training and serving + parameters of an + [Engine][google.cloud.discoveryengine.v1beta.Engine]. + + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "post", + "uri": "/v1beta/{name=projects/*/locations/*/collections/*/engines/*}:pause", + "body": "*", + }, + ] + request, metadata = self._interceptor.pre_pause_engine(request, metadata) + pb_request = engine_service.PauseEngineRequest.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 = engine.Engine() + pb_resp = engine.Engine.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + resp = self._interceptor.post_pause_engine(resp) + return resp + + class _ResumeEngine(EngineServiceRestStub): + def __hash__(self): + return hash("ResumeEngine") + + __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: engine_service.ResumeEngineRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> engine.Engine: + r"""Call the resume engine method over HTTP. + + Args: + request (~.engine_service.ResumeEngineRequest): + The request object. Request for resuming training of an + engine. + 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: + ~.engine.Engine: + Metadata that describes the training and serving + parameters of an + [Engine][google.cloud.discoveryengine.v1beta.Engine]. + + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "post", + "uri": "/v1beta/{name=projects/*/locations/*/collections/*/engines/*}:resume", + "body": "*", + }, + ] + request, metadata = self._interceptor.pre_resume_engine(request, metadata) + pb_request = engine_service.ResumeEngineRequest.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 = engine.Engine() + pb_resp = engine.Engine.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + resp = self._interceptor.post_resume_engine(resp) + return resp + + class _TuneEngine(EngineServiceRestStub): + def __hash__(self): + return hash("TuneEngine") + + __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: engine_service.TuneEngineRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> operations_pb2.Operation: + r"""Call the tune engine method over HTTP. + + Args: + request (~.engine_service.TuneEngineRequest): + The request object. Request to manually start a tuning + process now (instead of waiting for the + periodically scheduled tuning to + happen). + 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": "/v1beta/{name=projects/*/locations/*/collections/*/engines/*}:tune", + "body": "*", + }, + ] + request, metadata = self._interceptor.pre_tune_engine(request, metadata) + pb_request = engine_service.TuneEngineRequest.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_tune_engine(resp) + return resp + class _UpdateEngine(EngineServiceRestStub): def __hash__(self): return hash("UpdateEngine") @@ -1014,6 +1391,30 @@ def list_engines( # In C++ this would require a dynamic_cast return self._ListEngines(self._session, self._host, self._interceptor) # type: ignore + @property + def pause_engine( + self, + ) -> Callable[[engine_service.PauseEngineRequest], engine.Engine]: + # 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._PauseEngine(self._session, self._host, self._interceptor) # type: ignore + + @property + def resume_engine( + self, + ) -> Callable[[engine_service.ResumeEngineRequest], engine.Engine]: + # 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._ResumeEngine(self._session, self._host, self._interceptor) # type: ignore + + @property + def tune_engine( + self, + ) -> Callable[[engine_service.TuneEngineRequest], 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._TuneEngine(self._session, self._host, self._interceptor) # type: ignore + @property def update_engine( self, diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/grounded_generation_service/__init__.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/grounded_generation_service/__init__.py new file mode 100644 index 000000000000..8a4c978a5f5e --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/grounded_generation_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 GroundedGenerationServiceAsyncClient +from .client import GroundedGenerationServiceClient + +__all__ = ( + "GroundedGenerationServiceClient", + "GroundedGenerationServiceAsyncClient", +) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/grounded_generation_service/async_client.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/grounded_generation_service/async_client.py new file mode 100644 index 000000000000..b8290ea1bd36 --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/grounded_generation_service/async_client.py @@ -0,0 +1,488 @@ +# -*- 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 functools +import re +from typing import ( + 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.discoveryengine_v1beta 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.cloud.discoveryengine_v1beta.types import ( + grounded_generation_service, + grounding, +) + +from .client import GroundedGenerationServiceClient +from .transports.base import DEFAULT_CLIENT_INFO, GroundedGenerationServiceTransport +from .transports.grpc_asyncio import GroundedGenerationServiceGrpcAsyncIOTransport + + +class GroundedGenerationServiceAsyncClient: + """Service for grounded generation.""" + + _client: GroundedGenerationServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = GroundedGenerationServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = GroundedGenerationServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + GroundedGenerationServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = GroundedGenerationServiceClient._DEFAULT_UNIVERSE + + grounding_config_path = staticmethod( + GroundedGenerationServiceClient.grounding_config_path + ) + parse_grounding_config_path = staticmethod( + GroundedGenerationServiceClient.parse_grounding_config_path + ) + common_billing_account_path = staticmethod( + GroundedGenerationServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + GroundedGenerationServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + GroundedGenerationServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + GroundedGenerationServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + GroundedGenerationServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + GroundedGenerationServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + GroundedGenerationServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + GroundedGenerationServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + GroundedGenerationServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + GroundedGenerationServiceClient.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: + GroundedGenerationServiceAsyncClient: The constructed client. + """ + return GroundedGenerationServiceClient.from_service_account_info.__func__(GroundedGenerationServiceAsyncClient, 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: + GroundedGenerationServiceAsyncClient: The constructed client. + """ + return GroundedGenerationServiceClient.from_service_account_file.__func__(GroundedGenerationServiceAsyncClient, 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 GroundedGenerationServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> GroundedGenerationServiceTransport: + """Returns the transport used by the client instance. + + Returns: + GroundedGenerationServiceTransport: 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 = functools.partial( + type(GroundedGenerationServiceClient).get_transport_class, + type(GroundedGenerationServiceClient), + ) + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Union[str, GroundedGenerationServiceTransport] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the grounded generation 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 (Union[str, ~.GroundedGenerationServiceTransport]): The + transport to use. 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 = GroundedGenerationServiceClient( + credentials=credentials, + transport=transport, + client_options=client_options, + client_info=client_info, + ) + + async def check_grounding( + self, + request: Optional[ + Union[grounded_generation_service.CheckGroundingRequest, dict] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> grounded_generation_service.CheckGroundingResponse: + r"""Performs a grounding check. + + .. 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 discoveryengine_v1beta + + async def sample_check_grounding(): + # Create a client + client = discoveryengine_v1beta.GroundedGenerationServiceAsyncClient() + + # Initialize request argument(s) + request = discoveryengine_v1beta.CheckGroundingRequest( + grounding_config="grounding_config_value", + ) + + # Make the request + response = await client.check_grounding(request=request) + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.discoveryengine_v1beta.types.CheckGroundingRequest, dict]]): + The request object. Request message for + [GroundedGenerationService.CheckGrounding][google.cloud.discoveryengine.v1beta.GroundedGenerationService.CheckGrounding] + 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.cloud.discoveryengine_v1beta.types.CheckGroundingResponse: + Response message for the + [GroundedGenerationService.CheckGrounding][google.cloud.discoveryengine.v1beta.GroundedGenerationService.CheckGrounding] + method. + + """ + # Create or coerce a protobuf request object. + request = grounded_generation_service.CheckGroundingRequest(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.check_grounding, + 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( + (("grounding_config", request.grounding_config),) + ), + ) + + # 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) -> "GroundedGenerationServiceAsyncClient": + 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__ = ("GroundedGenerationServiceAsyncClient",) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/grounded_generation_service/client.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/grounded_generation_service/client.py new file mode 100644 index 000000000000..3fa6a1aeb6d5 --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/grounded_generation_service/client.py @@ -0,0 +1,900 @@ +# -*- 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 ( + 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.discoveryengine_v1beta 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.cloud.discoveryengine_v1beta.types import ( + grounded_generation_service, + grounding, +) + +from .transports.base import DEFAULT_CLIENT_INFO, GroundedGenerationServiceTransport +from .transports.grpc import GroundedGenerationServiceGrpcTransport +from .transports.grpc_asyncio import GroundedGenerationServiceGrpcAsyncIOTransport +from .transports.rest import GroundedGenerationServiceRestTransport + + +class GroundedGenerationServiceClientMeta(type): + """Metaclass for the GroundedGenerationService 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[GroundedGenerationServiceTransport]] + _transport_registry["grpc"] = GroundedGenerationServiceGrpcTransport + _transport_registry["grpc_asyncio"] = GroundedGenerationServiceGrpcAsyncIOTransport + _transport_registry["rest"] = GroundedGenerationServiceRestTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[GroundedGenerationServiceTransport]: + """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 GroundedGenerationServiceClient(metaclass=GroundedGenerationServiceClientMeta): + """Service for grounded generation.""" + + @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 = "discoveryengine.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "discoveryengine.{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: + GroundedGenerationServiceClient: 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: + GroundedGenerationServiceClient: 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) -> GroundedGenerationServiceTransport: + """Returns the transport used by the client instance. + + Returns: + GroundedGenerationServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def grounding_config_path( + project: str, + location: str, + grounding_config: str, + ) -> str: + """Returns a fully-qualified grounding_config string.""" + return "projects/{project}/locations/{location}/groundingConfigs/{grounding_config}".format( + project=project, + location=location, + grounding_config=grounding_config, + ) + + @staticmethod + def parse_grounding_config_path(path: str) -> Dict[str, str]: + """Parses a grounding_config path into its component segments.""" + m = re.match( + r"^projects/(?P.+?)/locations/(?P.+?)/groundingConfigs/(?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 = GroundedGenerationServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = GroundedGenerationServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + GroundedGenerationServiceClient._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 = GroundedGenerationServiceClient._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 = GroundedGenerationServiceClient._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 GroundedGenerationServiceClient._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, GroundedGenerationServiceTransport]] = None, + client_options: Optional[Union[client_options_lib.ClientOptions, dict]] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the grounded generation 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 (Union[str, GroundedGenerationServiceTransport]): The + transport to use. 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, + ) = GroundedGenerationServiceClient._read_environment_variables() + self._client_cert_source = ( + GroundedGenerationServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = GroundedGenerationServiceClient._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, GroundedGenerationServiceTransport) + if transport_provided: + # transport is a GroundedGenerationServiceTransport 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(GroundedGenerationServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or GroundedGenerationServiceClient._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 = type(self).get_transport_class(cast(str, transport)) + self._transport = Transport( + 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 check_grounding( + self, + request: Optional[ + Union[grounded_generation_service.CheckGroundingRequest, dict] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> grounded_generation_service.CheckGroundingResponse: + r"""Performs a grounding check. + + .. 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 discoveryengine_v1beta + + def sample_check_grounding(): + # Create a client + client = discoveryengine_v1beta.GroundedGenerationServiceClient() + + # Initialize request argument(s) + request = discoveryengine_v1beta.CheckGroundingRequest( + grounding_config="grounding_config_value", + ) + + # Make the request + response = client.check_grounding(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.discoveryengine_v1beta.types.CheckGroundingRequest, dict]): + The request object. Request message for + [GroundedGenerationService.CheckGrounding][google.cloud.discoveryengine.v1beta.GroundedGenerationService.CheckGrounding] + 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.cloud.discoveryengine_v1beta.types.CheckGroundingResponse: + Response message for the + [GroundedGenerationService.CheckGrounding][google.cloud.discoveryengine.v1beta.GroundedGenerationService.CheckGrounding] + method. + + """ + # Create or coerce a protobuf request object. + # Minor optimization to avoid making a copy if the user passes + # in a grounded_generation_service.CheckGroundingRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance(request, grounded_generation_service.CheckGroundingRequest): + request = grounded_generation_service.CheckGroundingRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.check_grounding] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("grounding_config", request.grounding_config),) + ), + ) + + # 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) -> "GroundedGenerationServiceClient": + 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__ = ("GroundedGenerationServiceClient",) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/grounded_generation_service/transports/__init__.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/grounded_generation_service/transports/__init__.py new file mode 100644 index 000000000000..b2598d761505 --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/grounded_generation_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 GroundedGenerationServiceTransport +from .grpc import GroundedGenerationServiceGrpcTransport +from .grpc_asyncio import GroundedGenerationServiceGrpcAsyncIOTransport +from .rest import ( + GroundedGenerationServiceRestInterceptor, + GroundedGenerationServiceRestTransport, +) + +# Compile a registry of transports. +_transport_registry = ( + OrderedDict() +) # type: Dict[str, Type[GroundedGenerationServiceTransport]] +_transport_registry["grpc"] = GroundedGenerationServiceGrpcTransport +_transport_registry["grpc_asyncio"] = GroundedGenerationServiceGrpcAsyncIOTransport +_transport_registry["rest"] = GroundedGenerationServiceRestTransport + +__all__ = ( + "GroundedGenerationServiceTransport", + "GroundedGenerationServiceGrpcTransport", + "GroundedGenerationServiceGrpcAsyncIOTransport", + "GroundedGenerationServiceRestTransport", + "GroundedGenerationServiceRestInterceptor", +) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/grounded_generation_service/transports/base.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/grounded_generation_service/transports/base.py new file mode 100644 index 000000000000..98d9f091b6ad --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/grounded_generation_service/transports/base.py @@ -0,0 +1,185 @@ +# -*- 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.discoveryengine_v1beta import gapic_version as package_version +from google.cloud.discoveryengine_v1beta.types import grounded_generation_service + +DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=package_version.__version__ +) + + +class GroundedGenerationServiceTransport(abc.ABC): + """Abstract transport class for GroundedGenerationService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/cloud-platform",) + + DEFAULT_HOST: str = "discoveryengine.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: 'discoveryengine.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 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: + 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.check_grounding: gapic_v1.method.wrap_method( + self.check_grounding, + 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 check_grounding( + self, + ) -> Callable[ + [grounded_generation_service.CheckGroundingRequest], + Union[ + grounded_generation_service.CheckGroundingResponse, + Awaitable[grounded_generation_service.CheckGroundingResponse], + ], + ]: + 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__ = ("GroundedGenerationServiceTransport",) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/grounded_generation_service/transports/grpc.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/grounded_generation_service/transports/grpc.py new file mode 100644 index 000000000000..b20b5b7ead1c --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/grounded_generation_service/transports/grpc.py @@ -0,0 +1,306 @@ +# -*- 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.discoveryengine_v1beta.types import grounded_generation_service + +from .base import DEFAULT_CLIENT_INFO, GroundedGenerationServiceTransport + + +class GroundedGenerationServiceGrpcTransport(GroundedGenerationServiceTransport): + """gRPC backend transport for GroundedGenerationService. + + Service for grounded generation. + + 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 = "discoveryengine.googleapis.com", + credentials: Optional[ga_credentials.Credentials] = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + channel: Optional[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: 'discoveryengine.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 ``channel`` 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 ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): 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 ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + 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 channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + 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: + self._grpc_channel = type(self).create_channel( + 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 = "discoveryengine.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 check_grounding( + self, + ) -> Callable[ + [grounded_generation_service.CheckGroundingRequest], + grounded_generation_service.CheckGroundingResponse, + ]: + r"""Return a callable for the check grounding method over gRPC. + + Performs a grounding check. + + Returns: + Callable[[~.CheckGroundingRequest], + ~.CheckGroundingResponse]: + 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 "check_grounding" not in self._stubs: + self._stubs["check_grounding"] = self.grpc_channel.unary_unary( + "/google.cloud.discoveryengine.v1beta.GroundedGenerationService/CheckGrounding", + request_serializer=grounded_generation_service.CheckGroundingRequest.serialize, + response_deserializer=grounded_generation_service.CheckGroundingResponse.deserialize, + ) + return self._stubs["check_grounding"] + + 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__ = ("GroundedGenerationServiceGrpcTransport",) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/grounded_generation_service/transports/grpc_asyncio.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/grounded_generation_service/transports/grpc_asyncio.py new file mode 100644 index 000000000000..1cee97fa2d87 --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/grounded_generation_service/transports/grpc_asyncio.py @@ -0,0 +1,305 @@ +# -*- 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 gapic_v1, grpc_helpers_async +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.discoveryengine_v1beta.types import grounded_generation_service + +from .base import DEFAULT_CLIENT_INFO, GroundedGenerationServiceTransport +from .grpc import GroundedGenerationServiceGrpcTransport + + +class GroundedGenerationServiceGrpcAsyncIOTransport(GroundedGenerationServiceTransport): + """gRPC AsyncIO backend transport for GroundedGenerationService. + + Service for grounded generation. + + 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 = "discoveryengine.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`. + This argument is ignored if ``channel`` 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`. + 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 = "discoveryengine.googleapis.com", + credentials: Optional[ga_credentials.Credentials] = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + channel: Optional[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: 'discoveryengine.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 ``channel`` 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 ``channel`` 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[aio.Channel]): A ``Channel`` instance through + which to make calls. + 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 ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + 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 channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + 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: + self._grpc_channel = type(self).create_channel( + 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 check_grounding( + self, + ) -> Callable[ + [grounded_generation_service.CheckGroundingRequest], + Awaitable[grounded_generation_service.CheckGroundingResponse], + ]: + r"""Return a callable for the check grounding method over gRPC. + + Performs a grounding check. + + Returns: + Callable[[~.CheckGroundingRequest], + Awaitable[~.CheckGroundingResponse]]: + 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 "check_grounding" not in self._stubs: + self._stubs["check_grounding"] = self.grpc_channel.unary_unary( + "/google.cloud.discoveryengine.v1beta.GroundedGenerationService/CheckGrounding", + request_serializer=grounded_generation_service.CheckGroundingRequest.serialize, + response_deserializer=grounded_generation_service.CheckGroundingResponse.deserialize, + ) + return self._stubs["check_grounding"] + + 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__ = ("GroundedGenerationServiceGrpcAsyncIOTransport",) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/grounded_generation_service/transports/rest.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/grounded_generation_service/transports/rest.py new file mode 100644 index 000000000000..e46e5a34e079 --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/grounded_generation_service/transports/rest.py @@ -0,0 +1,603 @@ +# -*- 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.discoveryengine_v1beta.types import grounded_generation_service + +from .base import DEFAULT_CLIENT_INFO as BASE_DEFAULT_CLIENT_INFO +from .base import GroundedGenerationServiceTransport + +DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=BASE_DEFAULT_CLIENT_INFO.gapic_version, + grpc_version=None, + rest_version=requests_version, +) + + +class GroundedGenerationServiceRestInterceptor: + """Interceptor for GroundedGenerationService. + + 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 GroundedGenerationServiceRestTransport. + + .. code-block:: python + class MyCustomGroundedGenerationServiceInterceptor(GroundedGenerationServiceRestInterceptor): + def pre_check_grounding(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_check_grounding(self, response): + logging.log(f"Received response: {response}") + return response + + transport = GroundedGenerationServiceRestTransport(interceptor=MyCustomGroundedGenerationServiceInterceptor()) + client = GroundedGenerationServiceClient(transport=transport) + + + """ + + def pre_check_grounding( + self, + request: grounded_generation_service.CheckGroundingRequest, + metadata: Sequence[Tuple[str, str]], + ) -> Tuple[ + grounded_generation_service.CheckGroundingRequest, Sequence[Tuple[str, str]] + ]: + """Pre-rpc interceptor for check_grounding + + Override in a subclass to manipulate the request or metadata + before they are sent to the GroundedGenerationService server. + """ + return request, metadata + + def post_check_grounding( + self, response: grounded_generation_service.CheckGroundingResponse + ) -> grounded_generation_service.CheckGroundingResponse: + """Post-rpc interceptor for check_grounding + + Override in a subclass to manipulate the response + after it is returned by the GroundedGenerationService 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 GroundedGenerationService 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 GroundedGenerationService 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 GroundedGenerationService 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 GroundedGenerationService server but before + it is returned to user code. + """ + return response + + +@dataclasses.dataclass +class GroundedGenerationServiceRestStub: + _session: AuthorizedSession + _host: str + _interceptor: GroundedGenerationServiceRestInterceptor + + +class GroundedGenerationServiceRestTransport(GroundedGenerationServiceTransport): + """REST backend transport for GroundedGenerationService. + + Service for grounded generation. + + 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 = "discoveryengine.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[GroundedGenerationServiceRestInterceptor] = None, + api_audience: Optional[str] = None, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to (default: 'discoveryengine.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 GroundedGenerationServiceRestInterceptor() + self._prep_wrapped_messages(client_info) + + class _CheckGrounding(GroundedGenerationServiceRestStub): + def __hash__(self): + return hash("CheckGrounding") + + __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: grounded_generation_service.CheckGroundingRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> grounded_generation_service.CheckGroundingResponse: + r"""Call the check grounding method over HTTP. + + Args: + request (~.grounded_generation_service.CheckGroundingRequest): + The request object. Request message for + [GroundedGenerationService.CheckGrounding][google.cloud.discoveryengine.v1beta.GroundedGenerationService.CheckGrounding] + 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: + ~.grounded_generation_service.CheckGroundingResponse: + Response message for the + [GroundedGenerationService.CheckGrounding][google.cloud.discoveryengine.v1beta.GroundedGenerationService.CheckGrounding] + method. + + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "post", + "uri": "/v1beta/{grounding_config=projects/*/locations/*/groundingConfigs/*}:check", + "body": "*", + }, + ] + request, metadata = self._interceptor.pre_check_grounding(request, metadata) + pb_request = grounded_generation_service.CheckGroundingRequest.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 = grounded_generation_service.CheckGroundingResponse() + pb_resp = grounded_generation_service.CheckGroundingResponse.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + resp = self._interceptor.post_check_grounding(resp) + return resp + + @property + def check_grounding( + self, + ) -> Callable[ + [grounded_generation_service.CheckGroundingRequest], + grounded_generation_service.CheckGroundingResponse, + ]: + # 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._CheckGrounding(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(GroundedGenerationServiceRestStub): + 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": "/v1beta/{name=projects/*/locations/*/collections/*/dataConnector/operations/*}", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/collections/*/dataStores/*/branches/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/collections/*/dataStores/*/models/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/collections/*/dataStores/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/collections/*/dataStores/*/schemas/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/collections/*/dataStores/*/siteSearchEngine/operations/*}", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/collections/*/dataStores/*/siteSearchEngine/targetSites/operations/*}", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/collections/*/engines/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/collections/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/dataStores/*/branches/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/dataStores/*/models/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/dataStores/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1beta/{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(GroundedGenerationServiceRestStub): + 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": "/v1beta/{name=projects/*/locations/*/collections/*/dataConnector}/operations", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/collections/*/dataStores/*/branches/*}/operations", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/collections/*/dataStores/*/models/*}/operations", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/collections/*/dataStores/*/schemas/*}/operations", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/collections/*/dataStores/*/siteSearchEngine/targetSites}/operations", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/collections/*/dataStores/*/siteSearchEngine}/operations", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/collections/*/dataStores/*}/operations", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/collections/*/engines/*}/operations", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/collections/*}/operations", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/dataStores/*/branches/*}/operations", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/dataStores/*/models/*}/operations", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/dataStores/*}/operations", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*}/operations", + }, + { + "method": "get", + "uri": "/v1beta/{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__ = ("GroundedGenerationServiceRestTransport",) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/rank_service/__init__.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/rank_service/__init__.py new file mode 100644 index 000000000000..f34036ed49c9 --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/rank_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 RankServiceAsyncClient +from .client import RankServiceClient + +__all__ = ( + "RankServiceClient", + "RankServiceAsyncClient", +) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/rank_service/async_client.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/rank_service/async_client.py new file mode 100644 index 000000000000..4c2426eafb8f --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/rank_service/async_client.py @@ -0,0 +1,469 @@ +# -*- 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 functools +import re +from typing import ( + 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.discoveryengine_v1beta 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.cloud.discoveryengine_v1beta.types import rank_service + +from .client import RankServiceClient +from .transports.base import DEFAULT_CLIENT_INFO, RankServiceTransport +from .transports.grpc_asyncio import RankServiceGrpcAsyncIOTransport + + +class RankServiceAsyncClient: + """Service for ranking text records.""" + + _client: RankServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = RankServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = RankServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = RankServiceClient._DEFAULT_ENDPOINT_TEMPLATE + _DEFAULT_UNIVERSE = RankServiceClient._DEFAULT_UNIVERSE + + ranking_config_path = staticmethod(RankServiceClient.ranking_config_path) + parse_ranking_config_path = staticmethod( + RankServiceClient.parse_ranking_config_path + ) + common_billing_account_path = staticmethod( + RankServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + RankServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod(RankServiceClient.common_folder_path) + parse_common_folder_path = staticmethod(RankServiceClient.parse_common_folder_path) + common_organization_path = staticmethod(RankServiceClient.common_organization_path) + parse_common_organization_path = staticmethod( + RankServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod(RankServiceClient.common_project_path) + parse_common_project_path = staticmethod( + RankServiceClient.parse_common_project_path + ) + common_location_path = staticmethod(RankServiceClient.common_location_path) + parse_common_location_path = staticmethod( + RankServiceClient.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: + RankServiceAsyncClient: The constructed client. + """ + return RankServiceClient.from_service_account_info.__func__(RankServiceAsyncClient, 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: + RankServiceAsyncClient: The constructed client. + """ + return RankServiceClient.from_service_account_file.__func__(RankServiceAsyncClient, 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 RankServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> RankServiceTransport: + """Returns the transport used by the client instance. + + Returns: + RankServiceTransport: 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 = functools.partial( + type(RankServiceClient).get_transport_class, type(RankServiceClient) + ) + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Union[str, RankServiceTransport] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the rank 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 (Union[str, ~.RankServiceTransport]): The + transport to use. 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 = RankServiceClient( + credentials=credentials, + transport=transport, + client_options=client_options, + client_info=client_info, + ) + + async def rank( + self, + request: Optional[Union[rank_service.RankRequest, dict]] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> rank_service.RankResponse: + r"""Ranks a list of text records based on the given input + query. + + .. 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 discoveryengine_v1beta + + async def sample_rank(): + # Create a client + client = discoveryengine_v1beta.RankServiceAsyncClient() + + # Initialize request argument(s) + request = discoveryengine_v1beta.RankRequest( + ranking_config="ranking_config_value", + ) + + # Make the request + response = await client.rank(request=request) + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.discoveryengine_v1beta.types.RankRequest, dict]]): + The request object. Request message for + [RankService.Rank][google.cloud.discoveryengine.v1beta.RankService.Rank] + 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.cloud.discoveryengine_v1beta.types.RankResponse: + Response message for + [RankService.Rank][google.cloud.discoveryengine.v1beta.RankService.Rank] + method. + + """ + # Create or coerce a protobuf request object. + request = rank_service.RankRequest(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.rank, + 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( + (("ranking_config", request.ranking_config),) + ), + ) + + # 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) -> "RankServiceAsyncClient": + 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__ = ("RankServiceAsyncClient",) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/rank_service/client.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/rank_service/client.py new file mode 100644 index 000000000000..84b344497085 --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/rank_service/client.py @@ -0,0 +1,887 @@ +# -*- 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 ( + 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.discoveryengine_v1beta 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.cloud.discoveryengine_v1beta.types import rank_service + +from .transports.base import DEFAULT_CLIENT_INFO, RankServiceTransport +from .transports.grpc import RankServiceGrpcTransport +from .transports.grpc_asyncio import RankServiceGrpcAsyncIOTransport +from .transports.rest import RankServiceRestTransport + + +class RankServiceClientMeta(type): + """Metaclass for the RankService 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[RankServiceTransport]] + _transport_registry["grpc"] = RankServiceGrpcTransport + _transport_registry["grpc_asyncio"] = RankServiceGrpcAsyncIOTransport + _transport_registry["rest"] = RankServiceRestTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[RankServiceTransport]: + """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 RankServiceClient(metaclass=RankServiceClientMeta): + """Service for ranking text records.""" + + @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 = "discoveryengine.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "discoveryengine.{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: + RankServiceClient: 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: + RankServiceClient: 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) -> RankServiceTransport: + """Returns the transport used by the client instance. + + Returns: + RankServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def ranking_config_path( + project: str, + location: str, + ranking_config: str, + ) -> str: + """Returns a fully-qualified ranking_config string.""" + return "projects/{project}/locations/{location}/rankingConfigs/{ranking_config}".format( + project=project, + location=location, + ranking_config=ranking_config, + ) + + @staticmethod + def parse_ranking_config_path(path: str) -> Dict[str, str]: + """Parses a ranking_config path into its component segments.""" + m = re.match( + r"^projects/(?P.+?)/locations/(?P.+?)/rankingConfigs/(?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 = RankServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = RankServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = RankServiceClient._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 = RankServiceClient._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 = RankServiceClient._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 RankServiceClient._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, RankServiceTransport]] = None, + client_options: Optional[Union[client_options_lib.ClientOptions, dict]] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the rank 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 (Union[str, RankServiceTransport]): The + transport to use. 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, + ) = RankServiceClient._read_environment_variables() + self._client_cert_source = RankServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + self._universe_domain = RankServiceClient._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, RankServiceTransport) + if transport_provided: + # transport is a RankServiceTransport 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(RankServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = self._api_endpoint or RankServiceClient._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 = type(self).get_transport_class(cast(str, transport)) + self._transport = Transport( + 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 rank( + self, + request: Optional[Union[rank_service.RankRequest, dict]] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, str]] = (), + ) -> rank_service.RankResponse: + r"""Ranks a list of text records based on the given input + query. + + .. 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 discoveryengine_v1beta + + def sample_rank(): + # Create a client + client = discoveryengine_v1beta.RankServiceClient() + + # Initialize request argument(s) + request = discoveryengine_v1beta.RankRequest( + ranking_config="ranking_config_value", + ) + + # Make the request + response = client.rank(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.discoveryengine_v1beta.types.RankRequest, dict]): + The request object. Request message for + [RankService.Rank][google.cloud.discoveryengine.v1beta.RankService.Rank] + 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.cloud.discoveryengine_v1beta.types.RankResponse: + Response message for + [RankService.Rank][google.cloud.discoveryengine.v1beta.RankService.Rank] + method. + + """ + # Create or coerce a protobuf request object. + # Minor optimization to avoid making a copy if the user passes + # in a rank_service.RankRequest. + # There's no risk of modifying the input as we've already verified + # there are no flattened fields. + if not isinstance(request, rank_service.RankRequest): + request = rank_service.RankRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.rank] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("ranking_config", request.ranking_config),) + ), + ) + + # 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) -> "RankServiceClient": + 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__ = ("RankServiceClient",) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/rank_service/transports/__init__.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/rank_service/transports/__init__.py new file mode 100644 index 000000000000..0084baa3bfcc --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/rank_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 RankServiceTransport +from .grpc import RankServiceGrpcTransport +from .grpc_asyncio import RankServiceGrpcAsyncIOTransport +from .rest import RankServiceRestInterceptor, RankServiceRestTransport + +# Compile a registry of transports. +_transport_registry = OrderedDict() # type: Dict[str, Type[RankServiceTransport]] +_transport_registry["grpc"] = RankServiceGrpcTransport +_transport_registry["grpc_asyncio"] = RankServiceGrpcAsyncIOTransport +_transport_registry["rest"] = RankServiceRestTransport + +__all__ = ( + "RankServiceTransport", + "RankServiceGrpcTransport", + "RankServiceGrpcAsyncIOTransport", + "RankServiceRestTransport", + "RankServiceRestInterceptor", +) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/rank_service/transports/base.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/rank_service/transports/base.py new file mode 100644 index 000000000000..b16166fde489 --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/rank_service/transports/base.py @@ -0,0 +1,182 @@ +# -*- 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.discoveryengine_v1beta import gapic_version as package_version +from google.cloud.discoveryengine_v1beta.types import rank_service + +DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=package_version.__version__ +) + + +class RankServiceTransport(abc.ABC): + """Abstract transport class for RankService.""" + + AUTH_SCOPES = ("https://www.googleapis.com/auth/cloud-platform",) + + DEFAULT_HOST: str = "discoveryengine.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: 'discoveryengine.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 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: + 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.rank: gapic_v1.method.wrap_method( + self.rank, + 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 rank( + self, + ) -> Callable[ + [rank_service.RankRequest], + Union[rank_service.RankResponse, Awaitable[rank_service.RankResponse]], + ]: + 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__ = ("RankServiceTransport",) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/rank_service/transports/grpc.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/rank_service/transports/grpc.py new file mode 100644 index 000000000000..a25dfd84c7d7 --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/rank_service/transports/grpc.py @@ -0,0 +1,302 @@ +# -*- 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.discoveryengine_v1beta.types import rank_service + +from .base import DEFAULT_CLIENT_INFO, RankServiceTransport + + +class RankServiceGrpcTransport(RankServiceTransport): + """gRPC backend transport for RankService. + + Service for ranking text records. + + 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 = "discoveryengine.googleapis.com", + credentials: Optional[ga_credentials.Credentials] = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + channel: Optional[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: 'discoveryengine.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 ``channel`` 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 ``channel`` is provided. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if ``channel`` is provided. + channel (Optional[grpc.Channel]): A ``Channel`` instance through + which to make calls. + api_mtls_endpoint (Optional[str]): 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 ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + 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 channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + 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: + self._grpc_channel = type(self).create_channel( + 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 = "discoveryengine.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 rank(self) -> Callable[[rank_service.RankRequest], rank_service.RankResponse]: + r"""Return a callable for the rank method over gRPC. + + Ranks a list of text records based on the given input + query. + + Returns: + Callable[[~.RankRequest], + ~.RankResponse]: + 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 "rank" not in self._stubs: + self._stubs["rank"] = self.grpc_channel.unary_unary( + "/google.cloud.discoveryengine.v1beta.RankService/Rank", + request_serializer=rank_service.RankRequest.serialize, + response_deserializer=rank_service.RankResponse.deserialize, + ) + return self._stubs["rank"] + + 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__ = ("RankServiceGrpcTransport",) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/rank_service/transports/grpc_asyncio.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/rank_service/transports/grpc_asyncio.py new file mode 100644 index 000000000000..e4192ee50136 --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/rank_service/transports/grpc_asyncio.py @@ -0,0 +1,303 @@ +# -*- 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 gapic_v1, grpc_helpers_async +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.discoveryengine_v1beta.types import rank_service + +from .base import DEFAULT_CLIENT_INFO, RankServiceTransport +from .grpc import RankServiceGrpcTransport + + +class RankServiceGrpcAsyncIOTransport(RankServiceTransport): + """gRPC AsyncIO backend transport for RankService. + + Service for ranking text records. + + 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 = "discoveryengine.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`. + This argument is ignored if ``channel`` 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`. + 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 = "discoveryengine.googleapis.com", + credentials: Optional[ga_credentials.Credentials] = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + channel: Optional[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: 'discoveryengine.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 ``channel`` 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 ``channel`` 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[aio.Channel]): A ``Channel`` instance through + which to make calls. + 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 ``channel`` is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if ``channel`` or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + 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 channel: + # Ignore credentials if a channel was passed. + credentials = False + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + 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: + self._grpc_channel = type(self).create_channel( + 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 rank( + self, + ) -> Callable[[rank_service.RankRequest], Awaitable[rank_service.RankResponse]]: + r"""Return a callable for the rank method over gRPC. + + Ranks a list of text records based on the given input + query. + + Returns: + Callable[[~.RankRequest], + Awaitable[~.RankResponse]]: + 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 "rank" not in self._stubs: + self._stubs["rank"] = self.grpc_channel.unary_unary( + "/google.cloud.discoveryengine.v1beta.RankService/Rank", + request_serializer=rank_service.RankRequest.serialize, + response_deserializer=rank_service.RankResponse.deserialize, + ) + return self._stubs["rank"] + + 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__ = ("RankServiceGrpcAsyncIOTransport",) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/rank_service/transports/rest.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/rank_service/transports/rest.py new file mode 100644 index 000000000000..5e5e71bfe43b --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/rank_service/transports/rest.py @@ -0,0 +1,594 @@ +# -*- 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.discoveryengine_v1beta.types import rank_service + +from .base import DEFAULT_CLIENT_INFO as BASE_DEFAULT_CLIENT_INFO +from .base import RankServiceTransport + +DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=BASE_DEFAULT_CLIENT_INFO.gapic_version, + grpc_version=None, + rest_version=requests_version, +) + + +class RankServiceRestInterceptor: + """Interceptor for RankService. + + 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 RankServiceRestTransport. + + .. code-block:: python + class MyCustomRankServiceInterceptor(RankServiceRestInterceptor): + def pre_rank(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_rank(self, response): + logging.log(f"Received response: {response}") + return response + + transport = RankServiceRestTransport(interceptor=MyCustomRankServiceInterceptor()) + client = RankServiceClient(transport=transport) + + + """ + + def pre_rank( + self, request: rank_service.RankRequest, metadata: Sequence[Tuple[str, str]] + ) -> Tuple[rank_service.RankRequest, Sequence[Tuple[str, str]]]: + """Pre-rpc interceptor for rank + + Override in a subclass to manipulate the request or metadata + before they are sent to the RankService server. + """ + return request, metadata + + def post_rank( + self, response: rank_service.RankResponse + ) -> rank_service.RankResponse: + """Post-rpc interceptor for rank + + Override in a subclass to manipulate the response + after it is returned by the RankService 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 RankService 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 RankService 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 RankService 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 RankService server but before + it is returned to user code. + """ + return response + + +@dataclasses.dataclass +class RankServiceRestStub: + _session: AuthorizedSession + _host: str + _interceptor: RankServiceRestInterceptor + + +class RankServiceRestTransport(RankServiceTransport): + """REST backend transport for RankService. + + Service for ranking text records. + + 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 = "discoveryengine.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[RankServiceRestInterceptor] = None, + api_audience: Optional[str] = None, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to (default: 'discoveryengine.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 RankServiceRestInterceptor() + self._prep_wrapped_messages(client_info) + + class _Rank(RankServiceRestStub): + def __hash__(self): + return hash("Rank") + + __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: rank_service.RankRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, str]] = (), + ) -> rank_service.RankResponse: + r"""Call the rank method over HTTP. + + Args: + request (~.rank_service.RankRequest): + The request object. Request message for + [RankService.Rank][google.cloud.discoveryengine.v1beta.RankService.Rank] + 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: + ~.rank_service.RankResponse: + Response message for + [RankService.Rank][google.cloud.discoveryengine.v1beta.RankService.Rank] + method. + + """ + + http_options: List[Dict[str, str]] = [ + { + "method": "post", + "uri": "/v1beta/{ranking_config=projects/*/locations/*/rankingConfigs/*}:rank", + "body": "*", + }, + ] + request, metadata = self._interceptor.pre_rank(request, metadata) + pb_request = rank_service.RankRequest.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 = rank_service.RankResponse() + pb_resp = rank_service.RankResponse.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + resp = self._interceptor.post_rank(resp) + return resp + + @property + def rank(self) -> Callable[[rank_service.RankRequest], rank_service.RankResponse]: + # 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._Rank(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(RankServiceRestStub): + 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": "/v1beta/{name=projects/*/locations/*/collections/*/dataConnector/operations/*}", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/collections/*/dataStores/*/branches/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/collections/*/dataStores/*/models/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/collections/*/dataStores/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/collections/*/dataStores/*/schemas/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/collections/*/dataStores/*/siteSearchEngine/operations/*}", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/collections/*/dataStores/*/siteSearchEngine/targetSites/operations/*}", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/collections/*/engines/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/collections/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/dataStores/*/branches/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/dataStores/*/models/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/dataStores/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1beta/{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(RankServiceRestStub): + 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": "/v1beta/{name=projects/*/locations/*/collections/*/dataConnector}/operations", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/collections/*/dataStores/*/branches/*}/operations", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/collections/*/dataStores/*/models/*}/operations", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/collections/*/dataStores/*/schemas/*}/operations", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/collections/*/dataStores/*/siteSearchEngine/targetSites}/operations", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/collections/*/dataStores/*/siteSearchEngine}/operations", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/collections/*/dataStores/*}/operations", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/collections/*/engines/*}/operations", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/collections/*}/operations", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/dataStores/*/branches/*}/operations", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/dataStores/*/models/*}/operations", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/dataStores/*}/operations", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*}/operations", + }, + { + "method": "get", + "uri": "/v1beta/{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__ = ("RankServiceRestTransport",) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/serving_config_service/async_client.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/serving_config_service/async_client.py index bf092a3c2ea1..08978b20363d 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/serving_config_service/async_client.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/serving_config_service/async_client.py @@ -302,7 +302,7 @@ async def sample_update_serving_config(): serving_config = discoveryengine_v1beta.ServingConfig() serving_config.media_config.content_watched_percentage_threshold = 0.3811 serving_config.display_name = "display_name_value" - serving_config.solution_type = "SOLUTION_TYPE_CHAT" + serving_config.solution_type = "SOLUTION_TYPE_GENERATIVE_CHAT" request = discoveryengine_v1beta.UpdateServingConfigRequest( serving_config=serving_config, diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/serving_config_service/client.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/serving_config_service/client.py index 44c96350323d..334044486141 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/serving_config_service/client.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/serving_config_service/client.py @@ -714,7 +714,7 @@ def sample_update_serving_config(): serving_config = discoveryengine_v1beta.ServingConfig() serving_config.media_config.content_watched_percentage_threshold = 0.3811 serving_config.display_name = "display_name_value" - serving_config.solution_type = "SOLUTION_TYPE_CHAT" + serving_config.solution_type = "SOLUTION_TYPE_GENERATIVE_CHAT" request = discoveryengine_v1beta.UpdateServingConfigRequest( serving_config=serving_config, diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/__init__.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/__init__.py index 6337b862284b..322aa6aed29b 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/__init__.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/__init__.py @@ -13,6 +13,7 @@ # See the License for the specific language governing permissions and # limitations under the License. # +from .answer import Answer from .common import ( CustomAttribute, DoubleList, @@ -34,14 +35,23 @@ TextInput, ) from .conversational_search_service import ( + AnswerQueryRequest, + AnswerQueryResponse, ConverseConversationRequest, ConverseConversationResponse, CreateConversationRequest, + CreateSessionRequest, DeleteConversationRequest, + DeleteSessionRequest, + GetAnswerRequest, GetConversationRequest, + GetSessionRequest, ListConversationsRequest, ListConversationsResponse, + ListSessionsRequest, + ListSessionsResponse, UpdateConversationRequest, + UpdateSessionRequest, ) from .data_store import DataStore from .data_store_service import ( @@ -73,10 +83,26 @@ GetEngineRequest, ListEnginesRequest, ListEnginesResponse, + PauseEngineRequest, + ResumeEngineRequest, + TuneEngineMetadata, + TuneEngineRequest, + TuneEngineResponse, UpdateEngineRequest, ) +from .grounded_generation_service import ( + CheckGroundingRequest, + CheckGroundingResponse, + CheckGroundingSpec, +) +from .grounding import FactChunk, GroundingFact from .import_config import ( BigQuerySource, + BigtableOptions, + BigtableSource, + CloudSqlSource, + FhirStoreSource, + FirestoreSource, GcsSource, ImportDocumentsMetadata, ImportDocumentsRequest, @@ -88,6 +114,7 @@ ImportUserEventsMetadata, ImportUserEventsRequest, ImportUserEventsResponse, + SpannerSource, ) from .purge_config import ( PurgeDocumentsMetadata, @@ -97,6 +124,7 @@ PurgeSuggestionDenyListEntriesRequest, PurgeSuggestionDenyListEntriesResponse, ) +from .rank_service import RankingRecord, RankRequest, RankResponse from .recommendation_service import RecommendRequest, RecommendResponse from .schema import Schema from .schema_service import ( @@ -123,6 +151,7 @@ ListServingConfigsResponse, UpdateServingConfigRequest, ) +from .session import Query, Session from .site_search_engine import SiteSearchEngine, SiteVerificationInfo, TargetSite from .site_search_engine_service import ( BatchCreateTargetSiteMetadata, @@ -166,6 +195,7 @@ from .user_event_service import CollectUserEventRequest, WriteUserEventRequest __all__ = ( + "Answer", "CustomAttribute", "DoubleList", "EmbeddingConfig", @@ -183,14 +213,23 @@ "ConversationMessage", "Reply", "TextInput", + "AnswerQueryRequest", + "AnswerQueryResponse", "ConverseConversationRequest", "ConverseConversationResponse", "CreateConversationRequest", + "CreateSessionRequest", "DeleteConversationRequest", + "DeleteSessionRequest", + "GetAnswerRequest", "GetConversationRequest", + "GetSessionRequest", "ListConversationsRequest", "ListConversationsResponse", + "ListSessionsRequest", + "ListSessionsResponse", "UpdateConversationRequest", + "UpdateSessionRequest", "DataStore", "CreateDataStoreMetadata", "CreateDataStoreRequest", @@ -216,8 +255,23 @@ "GetEngineRequest", "ListEnginesRequest", "ListEnginesResponse", + "PauseEngineRequest", + "ResumeEngineRequest", + "TuneEngineMetadata", + "TuneEngineRequest", + "TuneEngineResponse", "UpdateEngineRequest", + "CheckGroundingRequest", + "CheckGroundingResponse", + "CheckGroundingSpec", + "FactChunk", + "GroundingFact", "BigQuerySource", + "BigtableOptions", + "BigtableSource", + "CloudSqlSource", + "FhirStoreSource", + "FirestoreSource", "GcsSource", "ImportDocumentsMetadata", "ImportDocumentsRequest", @@ -229,12 +283,16 @@ "ImportUserEventsMetadata", "ImportUserEventsRequest", "ImportUserEventsResponse", + "SpannerSource", "PurgeDocumentsMetadata", "PurgeDocumentsRequest", "PurgeDocumentsResponse", "PurgeSuggestionDenyListEntriesMetadata", "PurgeSuggestionDenyListEntriesRequest", "PurgeSuggestionDenyListEntriesResponse", + "RankingRecord", + "RankRequest", + "RankResponse", "RecommendRequest", "RecommendResponse", "Schema", @@ -257,6 +315,8 @@ "ListServingConfigsRequest", "ListServingConfigsResponse", "UpdateServingConfigRequest", + "Query", + "Session", "SiteSearchEngine", "SiteVerificationInfo", "TargetSite", diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/answer.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/answer.py new file mode 100644 index 000000000000..eeee75196a27 --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/answer.py @@ -0,0 +1,619 @@ +# -*- 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 timestamp_pb2 # type: ignore +import proto # type: ignore + +__protobuf__ = proto.module( + package="google.cloud.discoveryengine.v1beta", + manifest={ + "Answer", + }, +) + + +class Answer(proto.Message): + r"""Defines an answer. + + Attributes: + name (str): + Immutable. Fully qualified name + ``project/*/locations/global/collections/{collection}/engines/{engine}/sessions/*/answers/*`` + state (google.cloud.discoveryengine_v1beta.types.Answer.State): + The state of the answer generation. + answer_text (str): + The textual answer. + citations (MutableSequence[google.cloud.discoveryengine_v1beta.types.Answer.Citation]): + Citations. + references (MutableSequence[google.cloud.discoveryengine_v1beta.types.Answer.Reference]): + References. + related_questions (MutableSequence[str]): + Suggested related questions. + steps (MutableSequence[google.cloud.discoveryengine_v1beta.types.Answer.Step]): + Answer generation steps. + query_understanding_info (google.cloud.discoveryengine_v1beta.types.Answer.QueryUnderstandingInfo): + Query understanding information. + answer_skipped_reasons (MutableSequence[google.cloud.discoveryengine_v1beta.types.Answer.AnswerSkippedReason]): + Additional answer-skipped reasons. This + provides the reason for ignored cases. If + nothing is skipped, this field is not set. + create_time (google.protobuf.timestamp_pb2.Timestamp): + Output only. Answer creation timestamp. + complete_time (google.protobuf.timestamp_pb2.Timestamp): + Output only. Answer completed timestamp. + """ + + class State(proto.Enum): + r"""Enumeration of the state of the answer generation. + + Values: + STATE_UNSPECIFIED (0): + Unknown. + IN_PROGRESS (1): + Answer generation is currently in progress. + FAILED (2): + Answer generation currently failed. + SUCCEEDED (3): + Answer generation has succeeded. + """ + STATE_UNSPECIFIED = 0 + IN_PROGRESS = 1 + FAILED = 2 + SUCCEEDED = 3 + + class AnswerSkippedReason(proto.Enum): + r"""An enum for answer skipped reasons. + + Values: + ANSWER_SKIPPED_REASON_UNSPECIFIED (0): + Default value. The answer skipped reason is + not specified. + ADVERSARIAL_QUERY_IGNORED (1): + The adversarial query ignored case. + NON_ANSWER_SEEKING_QUERY_IGNORED (2): + The non-answer seeking query ignored case. + OUT_OF_DOMAIN_QUERY_IGNORED (3): + The out-of-domain query ignored case. + + Google skips the answer if there are no + high-relevance search results. + POTENTIAL_POLICY_VIOLATION (4): + The potential policy violation case. + + Google skips the answer if there is a potential + policy violation detected. This includes content + that may be violent or toxic. + """ + ANSWER_SKIPPED_REASON_UNSPECIFIED = 0 + ADVERSARIAL_QUERY_IGNORED = 1 + NON_ANSWER_SEEKING_QUERY_IGNORED = 2 + OUT_OF_DOMAIN_QUERY_IGNORED = 3 + POTENTIAL_POLICY_VIOLATION = 4 + + class Citation(proto.Message): + r"""Citation info for a segment. + + Attributes: + start_index (int): + Index indicates the start of the segment, + measured in bytes (UTF-8 unicode). + end_index (int): + End of the attributed segment, exclusive. + sources (MutableSequence[google.cloud.discoveryengine_v1beta.types.Answer.CitationSource]): + Citation sources for the attributed segment. + """ + + start_index: int = proto.Field( + proto.INT64, + number=1, + ) + end_index: int = proto.Field( + proto.INT64, + number=2, + ) + sources: MutableSequence["Answer.CitationSource"] = proto.RepeatedField( + proto.MESSAGE, + number=3, + message="Answer.CitationSource", + ) + + class CitationSource(proto.Message): + r"""Citation source. + + Attributes: + reference_id (str): + ID of the citation source. + """ + + reference_id: str = proto.Field( + proto.STRING, + number=1, + ) + + class Reference(proto.Message): + r"""Reference. + + 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: + unstructured_document_info (google.cloud.discoveryengine_v1beta.types.Answer.Reference.UnstructuredDocumentInfo): + Unstructured document information. + + This field is a member of `oneof`_ ``content``. + chunk_info (google.cloud.discoveryengine_v1beta.types.Answer.Reference.ChunkInfo): + Chunk information. + + This field is a member of `oneof`_ ``content``. + """ + + class UnstructuredDocumentInfo(proto.Message): + r"""Unstructured document information. + + Attributes: + document (str): + Document resource name. + uri (str): + URI for the document. + title (str): + Title. + chunk_contents (MutableSequence[google.cloud.discoveryengine_v1beta.types.Answer.Reference.UnstructuredDocumentInfo.ChunkContent]): + List of cited chunk contents derived from + document content. + """ + + class ChunkContent(proto.Message): + r"""Chunk content. + + Attributes: + content (str): + Chunk textual content. + page_identifier (str): + Page identifier. + """ + + content: str = proto.Field( + proto.STRING, + number=1, + ) + page_identifier: str = proto.Field( + proto.STRING, + number=2, + ) + + document: str = proto.Field( + proto.STRING, + number=1, + ) + uri: str = proto.Field( + proto.STRING, + number=2, + ) + title: str = proto.Field( + proto.STRING, + number=3, + ) + chunk_contents: MutableSequence[ + "Answer.Reference.UnstructuredDocumentInfo.ChunkContent" + ] = proto.RepeatedField( + proto.MESSAGE, + number=4, + message="Answer.Reference.UnstructuredDocumentInfo.ChunkContent", + ) + + class ChunkInfo(proto.Message): + r"""Chunk information. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + chunk (str): + Chunk resource name. + content (str): + Chunk textual content. + relevance_score (float): + Relevance score. + + This field is a member of `oneof`_ ``_relevance_score``. + document_metadata (google.cloud.discoveryengine_v1beta.types.Answer.Reference.ChunkInfo.DocumentMetadata): + Document metadata. + """ + + class DocumentMetadata(proto.Message): + r"""Document metadata. + + Attributes: + document (str): + Document resource name. + uri (str): + URI for the document. + title (str): + Title. + page_identifier (str): + Page identifier. + """ + + document: str = proto.Field( + proto.STRING, + number=1, + ) + uri: str = proto.Field( + proto.STRING, + number=2, + ) + title: str = proto.Field( + proto.STRING, + number=3, + ) + page_identifier: str = proto.Field( + proto.STRING, + number=4, + ) + + chunk: str = proto.Field( + proto.STRING, + number=1, + ) + content: str = proto.Field( + proto.STRING, + number=2, + ) + relevance_score: float = proto.Field( + proto.FLOAT, + number=3, + optional=True, + ) + document_metadata: "Answer.Reference.ChunkInfo.DocumentMetadata" = ( + proto.Field( + proto.MESSAGE, + number=4, + message="Answer.Reference.ChunkInfo.DocumentMetadata", + ) + ) + + unstructured_document_info: "Answer.Reference.UnstructuredDocumentInfo" = ( + proto.Field( + proto.MESSAGE, + number=1, + oneof="content", + message="Answer.Reference.UnstructuredDocumentInfo", + ) + ) + chunk_info: "Answer.Reference.ChunkInfo" = proto.Field( + proto.MESSAGE, + number=2, + oneof="content", + message="Answer.Reference.ChunkInfo", + ) + + class Step(proto.Message): + r"""Step information. + + Attributes: + state (google.cloud.discoveryengine_v1beta.types.Answer.Step.State): + The state of the step. + description (str): + The description of the step. + thought (str): + The thought of the step. + actions (MutableSequence[google.cloud.discoveryengine_v1beta.types.Answer.Step.Action]): + Actions. + """ + + class State(proto.Enum): + r"""Enumeration of the state of the step. + + Values: + STATE_UNSPECIFIED (0): + Unknown. + IN_PROGRESS (1): + Step is currently in progress. + FAILED (2): + Step currently failed. + SUCCEEDED (3): + Step has succeeded. + """ + STATE_UNSPECIFIED = 0 + IN_PROGRESS = 1 + FAILED = 2 + SUCCEEDED = 3 + + class Action(proto.Message): + r"""Action. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + search_action (google.cloud.discoveryengine_v1beta.types.Answer.Step.Action.SearchAction): + Search action. + + This field is a member of `oneof`_ ``action``. + observation (google.cloud.discoveryengine_v1beta.types.Answer.Step.Action.Observation): + Observation. + """ + + class SearchAction(proto.Message): + r"""Search action. + + Attributes: + query (str): + The query to search. + """ + + query: str = proto.Field( + proto.STRING, + number=1, + ) + + class Observation(proto.Message): + r"""Observation. + + Attributes: + search_results (MutableSequence[google.cloud.discoveryengine_v1beta.types.Answer.Step.Action.Observation.SearchResult]): + Search results observed by the search action, + it can be snippets info or chunk info, depending + on the citation type set by the user. + """ + + class SearchResult(proto.Message): + r""" + + Attributes: + document (str): + Document resource name. + uri (str): + URI for the document. + title (str): + Title. + snippet_info (MutableSequence[google.cloud.discoveryengine_v1beta.types.Answer.Step.Action.Observation.SearchResult.SnippetInfo]): + If citation_type is DOCUMENT_LEVEL_CITATION, populate + document level snippets. + chunk_info (MutableSequence[google.cloud.discoveryengine_v1beta.types.Answer.Step.Action.Observation.SearchResult.ChunkInfo]): + If citation_type is CHUNK_LEVEL_CITATION and chunk mode is + on, populate chunk info. + """ + + class SnippetInfo(proto.Message): + r"""Snippet information. + + Attributes: + snippet (str): + Snippet content. + snippet_status (str): + Status of the snippet defined by the search + team. + """ + + snippet: str = proto.Field( + proto.STRING, + number=1, + ) + snippet_status: str = proto.Field( + proto.STRING, + number=2, + ) + + class ChunkInfo(proto.Message): + r"""Chunk information. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + chunk (str): + Chunk resource name. + content (str): + Chunk textual content. + relevance_score (float): + Relevance score. + + This field is a member of `oneof`_ ``_relevance_score``. + """ + + chunk: str = proto.Field( + proto.STRING, + number=1, + ) + content: str = proto.Field( + proto.STRING, + number=2, + ) + relevance_score: float = proto.Field( + proto.FLOAT, + number=3, + optional=True, + ) + + document: str = proto.Field( + proto.STRING, + number=1, + ) + uri: str = proto.Field( + proto.STRING, + number=2, + ) + title: str = proto.Field( + proto.STRING, + number=3, + ) + snippet_info: MutableSequence[ + "Answer.Step.Action.Observation.SearchResult.SnippetInfo" + ] = proto.RepeatedField( + proto.MESSAGE, + number=4, + message="Answer.Step.Action.Observation.SearchResult.SnippetInfo", + ) + chunk_info: MutableSequence[ + "Answer.Step.Action.Observation.SearchResult.ChunkInfo" + ] = proto.RepeatedField( + proto.MESSAGE, + number=5, + message="Answer.Step.Action.Observation.SearchResult.ChunkInfo", + ) + + search_results: MutableSequence[ + "Answer.Step.Action.Observation.SearchResult" + ] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="Answer.Step.Action.Observation.SearchResult", + ) + + search_action: "Answer.Step.Action.SearchAction" = proto.Field( + proto.MESSAGE, + number=2, + oneof="action", + message="Answer.Step.Action.SearchAction", + ) + observation: "Answer.Step.Action.Observation" = proto.Field( + proto.MESSAGE, + number=3, + message="Answer.Step.Action.Observation", + ) + + state: "Answer.Step.State" = proto.Field( + proto.ENUM, + number=1, + enum="Answer.Step.State", + ) + description: str = proto.Field( + proto.STRING, + number=2, + ) + thought: str = proto.Field( + proto.STRING, + number=3, + ) + actions: MutableSequence["Answer.Step.Action"] = proto.RepeatedField( + proto.MESSAGE, + number=4, + message="Answer.Step.Action", + ) + + class QueryUnderstandingInfo(proto.Message): + r"""Query understanding information. + + Attributes: + query_classification_info (MutableSequence[google.cloud.discoveryengine_v1beta.types.Answer.QueryUnderstandingInfo.QueryClassificationInfo]): + Query classification information. + """ + + class QueryClassificationInfo(proto.Message): + r"""Query classification information. + + Attributes: + type_ (google.cloud.discoveryengine_v1beta.types.Answer.QueryUnderstandingInfo.QueryClassificationInfo.Type): + Query classification type. + positive (bool): + Classification output. + """ + + class Type(proto.Enum): + r"""Query classification types. + + Values: + TYPE_UNSPECIFIED (0): + Unspecified query classification type. + ADVERSARIAL_QUERY (1): + Adversarial query classification type. + NON_ANSWER_SEEKING_QUERY (2): + Non-answer-seeking query classification type. + """ + TYPE_UNSPECIFIED = 0 + ADVERSARIAL_QUERY = 1 + NON_ANSWER_SEEKING_QUERY = 2 + + type_: "Answer.QueryUnderstandingInfo.QueryClassificationInfo.Type" = ( + proto.Field( + proto.ENUM, + number=1, + enum="Answer.QueryUnderstandingInfo.QueryClassificationInfo.Type", + ) + ) + positive: bool = proto.Field( + proto.BOOL, + number=2, + ) + + query_classification_info: MutableSequence[ + "Answer.QueryUnderstandingInfo.QueryClassificationInfo" + ] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="Answer.QueryUnderstandingInfo.QueryClassificationInfo", + ) + + name: str = proto.Field( + proto.STRING, + number=1, + ) + state: State = proto.Field( + proto.ENUM, + number=2, + enum=State, + ) + answer_text: str = proto.Field( + proto.STRING, + number=3, + ) + citations: MutableSequence[Citation] = proto.RepeatedField( + proto.MESSAGE, + number=4, + message=Citation, + ) + references: MutableSequence[Reference] = proto.RepeatedField( + proto.MESSAGE, + number=5, + message=Reference, + ) + related_questions: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=6, + ) + steps: MutableSequence[Step] = proto.RepeatedField( + proto.MESSAGE, + number=7, + message=Step, + ) + query_understanding_info: QueryUnderstandingInfo = proto.Field( + proto.MESSAGE, + number=10, + message=QueryUnderstandingInfo, + ) + answer_skipped_reasons: MutableSequence[AnswerSkippedReason] = proto.RepeatedField( + proto.ENUM, + number=11, + enum=AnswerSkippedReason, + ) + create_time: timestamp_pb2.Timestamp = proto.Field( + proto.MESSAGE, + number=8, + message=timestamp_pb2.Timestamp, + ) + complete_time: timestamp_pb2.Timestamp = proto.Field( + proto.MESSAGE, + number=9, + message=timestamp_pb2.Timestamp, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/common.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/common.py index 61dc46d9f527..750a2d3c14dc 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/common.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/common.py @@ -47,10 +47,13 @@ class IndustryVertical(proto.Enum): not specific to any industry vertical. MEDIA (2): The media industry vertical. + HEALTHCARE_FHIR (7): + The healthcare FHIR vertical. """ INDUSTRY_VERTICAL_UNSPECIFIED = 0 GENERIC = 1 MEDIA = 2 + HEALTHCARE_FHIR = 7 class SolutionType(proto.Enum): @@ -66,16 +69,22 @@ class SolutionType(proto.Enum): SOLUTION_TYPE_CHAT (3): Used for use cases related to the Generative AI agent. + SOLUTION_TYPE_GENERATIVE_CHAT (4): + Used for use cases related to the Generative Chat agent. + It's used for Generative chat engine only, the associated + data stores must enrolled with ``SOLUTION_TYPE_CHAT`` + solution. """ SOLUTION_TYPE_UNSPECIFIED = 0 SOLUTION_TYPE_RECOMMENDATION = 1 SOLUTION_TYPE_SEARCH = 2 SOLUTION_TYPE_CHAT = 3 + SOLUTION_TYPE_GENERATIVE_CHAT = 4 class SearchTier(proto.Enum): r"""Tiers of search features. Different tiers might have - different pricing. To learn more, please check the pricing + different pricing. To learn more, check the pricing documentation. Values: diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/conversational_search_service.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/conversational_search_service.py index 90229705d7a5..2c96fff4d53b 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/conversational_search_service.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/conversational_search_service.py @@ -21,7 +21,9 @@ import proto # type: ignore from google.cloud.discoveryengine_v1beta.types import conversation as gcd_conversation +from google.cloud.discoveryengine_v1beta.types import answer as gcd_answer from google.cloud.discoveryengine_v1beta.types import search_service +from google.cloud.discoveryengine_v1beta.types import session as gcd_session __protobuf__ = proto.module( package="google.cloud.discoveryengine.v1beta", @@ -34,6 +36,15 @@ "GetConversationRequest", "ListConversationsRequest", "ListConversationsResponse", + "AnswerQueryRequest", + "AnswerQueryResponse", + "GetAnswerRequest", + "CreateSessionRequest", + "UpdateSessionRequest", + "DeleteSessionRequest", + "GetSessionRequest", + "ListSessionsRequest", + "ListSessionsResponse", }, ) @@ -362,4 +373,795 @@ def raw_page(self): ) +class AnswerQueryRequest(proto.Message): + r"""Request message for + [ConversationalSearchService.AnswerQuery][google.cloud.discoveryengine.v1beta.ConversationalSearchService.AnswerQuery] + method. + + Attributes: + serving_config (str): + Required. The resource name of the Search serving config, + such as + ``projects/*/locations/global/collections/default_collection/engines/*/servingConfigs/default_serving_config``, + or + ``projects/*/locations/global/collections/default_collection/dataStores/*/servingConfigs/default_serving_config``. + This field is used to identify the serving configuration + name, set of models used to make the search. + query (google.cloud.discoveryengine_v1beta.types.Query): + Required. Current user query. + session (str): + The session resource name. Not required. + + When session field is not set, the API is in + sessionless mode. + + We support auto session mode: users can use the + wildcard symbol “-” as session id. A new id + will be automatically generated and assigned. + safety_spec (google.cloud.discoveryengine_v1beta.types.AnswerQueryRequest.SafetySpec): + Model specification. + related_questions_spec (google.cloud.discoveryengine_v1beta.types.AnswerQueryRequest.RelatedQuestionsSpec): + Related questions specification. + answer_generation_spec (google.cloud.discoveryengine_v1beta.types.AnswerQueryRequest.AnswerGenerationSpec): + Answer generation specification. + search_spec (google.cloud.discoveryengine_v1beta.types.AnswerQueryRequest.SearchSpec): + Search specification. + query_understanding_spec (google.cloud.discoveryengine_v1beta.types.AnswerQueryRequest.QueryUnderstandingSpec): + Query understanding specification. + asynchronous_mode (bool): + Asynchronous mode control. + + If enabled, the response will be returned with + answer/session resource name without final answer. The API + users need to do the polling to get the latest status of + answer/session by calling + [ConversationalSearchService.GetAnswer][google.cloud.discoveryengine.v1beta.ConversationalSearchService.GetAnswer] + or + [ConversationalSearchService.GetSession][google.cloud.discoveryengine.v1beta.ConversationalSearchService.GetSession] + method. + user_pseudo_id (str): + A unique identifier for tracking visitors. For example, this + could be implemented with an HTTP cookie, which should be + able to uniquely identify a visitor on a single device. This + unique identifier should not change if the visitor logs in + or out of the website. + + This field should NOT have a fixed value such as + ``unknown_visitor``. + + The field must be a UTF-8 encoded string with a length limit + of 128 characters. Otherwise, an ``INVALID_ARGUMENT`` error + is returned. + """ + + class SafetySpec(proto.Message): + r"""Safety specification. + + Attributes: + enable (bool): + Enable the safety filtering on the answer + response. It is false by default. + """ + + enable: bool = proto.Field( + proto.BOOL, + number=1, + ) + + class RelatedQuestionsSpec(proto.Message): + r"""Related questions specification. + + Attributes: + enable (bool): + Enable related questions feature if true. + """ + + enable: bool = proto.Field( + proto.BOOL, + number=1, + ) + + class AnswerGenerationSpec(proto.Message): + r"""Answer generation specification. + + Attributes: + model_spec (google.cloud.discoveryengine_v1beta.types.AnswerQueryRequest.AnswerGenerationSpec.ModelSpec): + Answer generation model specification. + prompt_spec (google.cloud.discoveryengine_v1beta.types.AnswerQueryRequest.AnswerGenerationSpec.PromptSpec): + Answer generation prompt specification. + include_citations (bool): + Specifies whether to include citation metadata in the + answer. The default value is ``false``. + answer_language_code (str): + Language code for Answer. Use language tags defined by + `BCP47 `__. + Note: This is an experimental feature. + ignore_adversarial_query (bool): + Specifies whether to filter out adversarial queries. The + default value is ``false``. + + Google employs search-query classification to detect + adversarial queries. No answer is returned if the search + query is classified as an adversarial query. For example, a + user might ask a question regarding negative comments about + the company or submit a query designed to generate unsafe, + policy-violating output. If this field is set to ``true``, + we skip generating answers for adversarial queries and + return fallback messages instead. + ignore_non_answer_seeking_query (bool): + Specifies whether to filter out queries that are not + answer-seeking. The default value is ``false``. + + Google employs search-query classification to detect + answer-seeking queries. No answer is returned if the search + query is classified as a non-answer seeking query. If this + field is set to ``true``, we skip generating answers for + non-answer seeking queries and return fallback messages + instead. + """ + + class ModelSpec(proto.Message): + r"""Answer Generation Model specification. + + Attributes: + model_version (str): + Model version. If not set, it will use the + default stable model. Allowed values are: + stable, preview. + """ + + model_version: str = proto.Field( + proto.STRING, + number=1, + ) + + class PromptSpec(proto.Message): + r"""Answer generation prompt specification. + + Attributes: + preamble (str): + Customized preamble. + """ + + preamble: str = proto.Field( + proto.STRING, + number=1, + ) + + model_spec: "AnswerQueryRequest.AnswerGenerationSpec.ModelSpec" = proto.Field( + proto.MESSAGE, + number=1, + message="AnswerQueryRequest.AnswerGenerationSpec.ModelSpec", + ) + prompt_spec: "AnswerQueryRequest.AnswerGenerationSpec.PromptSpec" = proto.Field( + proto.MESSAGE, + number=2, + message="AnswerQueryRequest.AnswerGenerationSpec.PromptSpec", + ) + include_citations: bool = proto.Field( + proto.BOOL, + number=3, + ) + answer_language_code: str = proto.Field( + proto.STRING, + number=4, + ) + ignore_adversarial_query: bool = proto.Field( + proto.BOOL, + number=5, + ) + ignore_non_answer_seeking_query: bool = proto.Field( + proto.BOOL, + number=6, + ) + + class SearchSpec(proto.Message): + r"""Search specification. + + 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: + search_params (google.cloud.discoveryengine_v1beta.types.AnswerQueryRequest.SearchSpec.SearchParams): + Search parameters. + + This field is a member of `oneof`_ ``input``. + search_result_list (google.cloud.discoveryengine_v1beta.types.AnswerQueryRequest.SearchSpec.SearchResultList): + Search result list. + + This field is a member of `oneof`_ ``input``. + """ + + class SearchParams(proto.Message): + r"""Search parameters. + + Attributes: + max_return_results (int): + Number of search results to return. + The default value is 10. + filter (str): + The filter syntax consists of an expression language for + constructing a predicate from one or more fields of the + documents being filtered. Filter expression is + case-sensitive. This will be used to filter search results + which may affect the Answer response. + + If this field is unrecognizable, an ``INVALID_ARGUMENT`` is + returned. + + Filtering in Vertex AI Search is done by mapping the LHS + filter key to a key property defined in the Vertex AI Search + backend -- this mapping is defined by the customer in their + schema. For example a media customers might have a field + 'name' in their schema. In this case the filter would look + like this: filter --> name:'ANY("king kong")' + + For more information about filtering including syntax and + filter operators, see + `Filter `__ + boost_spec (google.cloud.discoveryengine_v1beta.types.SearchRequest.BoostSpec): + Boost specification to boost certain documents in search + results which may affect the answer query response. For more + information on boosting, see + `Boosting `__ + order_by (str): + The order in which documents are returned. Documents can be + ordered by a field in an + [Document][google.cloud.discoveryengine.v1beta.Document] + object. Leave it unset if ordered by relevance. ``order_by`` + expression is case-sensitive. For more information on + ordering, see + `Ordering `__ + + If this field is unrecognizable, an ``INVALID_ARGUMENT`` is + returned. + """ + + max_return_results: int = proto.Field( + proto.INT32, + number=1, + ) + filter: str = proto.Field( + proto.STRING, + number=2, + ) + boost_spec: search_service.SearchRequest.BoostSpec = proto.Field( + proto.MESSAGE, + number=3, + message=search_service.SearchRequest.BoostSpec, + ) + order_by: str = proto.Field( + proto.STRING, + number=4, + ) + + class SearchResultList(proto.Message): + r"""Search result list. + + Attributes: + search_results (MutableSequence[google.cloud.discoveryengine_v1beta.types.AnswerQueryRequest.SearchSpec.SearchResultList.SearchResult]): + Search results. + """ + + class SearchResult(proto.Message): + r"""Search result. + + 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: + unstructured_document_info (google.cloud.discoveryengine_v1beta.types.AnswerQueryRequest.SearchSpec.SearchResultList.SearchResult.UnstructuredDocumentInfo): + Unstructured document information. + + This field is a member of `oneof`_ ``content``. + chunk_info (google.cloud.discoveryengine_v1beta.types.AnswerQueryRequest.SearchSpec.SearchResultList.SearchResult.ChunkInfo): + Chunk information. + + This field is a member of `oneof`_ ``content``. + """ + + class UnstructuredDocumentInfo(proto.Message): + r"""Unstructured document information. + + Attributes: + document (str): + Document resource name. + uri (str): + URI for the document. + title (str): + Title. + document_contexts (MutableSequence[google.cloud.discoveryengine_v1beta.types.AnswerQueryRequest.SearchSpec.SearchResultList.SearchResult.UnstructuredDocumentInfo.DocumentContext]): + List of document contexts. + extractive_segments (MutableSequence[google.cloud.discoveryengine_v1beta.types.AnswerQueryRequest.SearchSpec.SearchResultList.SearchResult.UnstructuredDocumentInfo.ExtractiveSegment]): + List of extractive segments. + extractive_answers (MutableSequence[google.cloud.discoveryengine_v1beta.types.AnswerQueryRequest.SearchSpec.SearchResultList.SearchResult.UnstructuredDocumentInfo.ExtractiveAnswer]): + List of extractive answers. + """ + + class DocumentContext(proto.Message): + r"""Document context. + + Attributes: + page_identifier (str): + Page identifier. + content (str): + Document content. + """ + + page_identifier: str = proto.Field( + proto.STRING, + number=1, + ) + content: str = proto.Field( + proto.STRING, + number=2, + ) + + class ExtractiveSegment(proto.Message): + r"""Extractive segment. + `Guide `__ + + Attributes: + page_identifier (str): + Page identifier. + content (str): + Extractive segment content. + """ + + page_identifier: str = proto.Field( + proto.STRING, + number=1, + ) + content: str = proto.Field( + proto.STRING, + number=2, + ) + + class ExtractiveAnswer(proto.Message): + r"""Extractive answer. + `Guide `__ + + Attributes: + page_identifier (str): + Page identifier. + content (str): + Extractive answer content. + """ + + page_identifier: str = proto.Field( + proto.STRING, + number=1, + ) + content: str = proto.Field( + proto.STRING, + number=2, + ) + + document: str = proto.Field( + proto.STRING, + number=1, + ) + uri: str = proto.Field( + proto.STRING, + number=2, + ) + title: str = proto.Field( + proto.STRING, + number=3, + ) + document_contexts: MutableSequence[ + "AnswerQueryRequest.SearchSpec.SearchResultList.SearchResult.UnstructuredDocumentInfo.DocumentContext" + ] = proto.RepeatedField( + proto.MESSAGE, + number=4, + message="AnswerQueryRequest.SearchSpec.SearchResultList.SearchResult.UnstructuredDocumentInfo.DocumentContext", + ) + extractive_segments: MutableSequence[ + "AnswerQueryRequest.SearchSpec.SearchResultList.SearchResult.UnstructuredDocumentInfo.ExtractiveSegment" + ] = proto.RepeatedField( + proto.MESSAGE, + number=5, + message="AnswerQueryRequest.SearchSpec.SearchResultList.SearchResult.UnstructuredDocumentInfo.ExtractiveSegment", + ) + extractive_answers: MutableSequence[ + "AnswerQueryRequest.SearchSpec.SearchResultList.SearchResult.UnstructuredDocumentInfo.ExtractiveAnswer" + ] = proto.RepeatedField( + proto.MESSAGE, + number=6, + message="AnswerQueryRequest.SearchSpec.SearchResultList.SearchResult.UnstructuredDocumentInfo.ExtractiveAnswer", + ) + + class ChunkInfo(proto.Message): + r"""Chunk information. + + Attributes: + chunk (str): + Chunk resource name. + content (str): + Chunk textual content. + """ + + chunk: str = proto.Field( + proto.STRING, + number=1, + ) + content: str = proto.Field( + proto.STRING, + number=2, + ) + + unstructured_document_info: "AnswerQueryRequest.SearchSpec.SearchResultList.SearchResult.UnstructuredDocumentInfo" = proto.Field( + proto.MESSAGE, + number=1, + oneof="content", + message="AnswerQueryRequest.SearchSpec.SearchResultList.SearchResult.UnstructuredDocumentInfo", + ) + chunk_info: "AnswerQueryRequest.SearchSpec.SearchResultList.SearchResult.ChunkInfo" = proto.Field( + proto.MESSAGE, + number=2, + oneof="content", + message="AnswerQueryRequest.SearchSpec.SearchResultList.SearchResult.ChunkInfo", + ) + + search_results: MutableSequence[ + "AnswerQueryRequest.SearchSpec.SearchResultList.SearchResult" + ] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="AnswerQueryRequest.SearchSpec.SearchResultList.SearchResult", + ) + + search_params: "AnswerQueryRequest.SearchSpec.SearchParams" = proto.Field( + proto.MESSAGE, + number=1, + oneof="input", + message="AnswerQueryRequest.SearchSpec.SearchParams", + ) + search_result_list: "AnswerQueryRequest.SearchSpec.SearchResultList" = ( + proto.Field( + proto.MESSAGE, + number=2, + oneof="input", + message="AnswerQueryRequest.SearchSpec.SearchResultList", + ) + ) + + class QueryUnderstandingSpec(proto.Message): + r"""Query understanding specification. + + Attributes: + query_classification_spec (google.cloud.discoveryengine_v1beta.types.AnswerQueryRequest.QueryUnderstandingSpec.QueryClassificationSpec): + Query classification specification. + query_rephraser_spec (google.cloud.discoveryengine_v1beta.types.AnswerQueryRequest.QueryUnderstandingSpec.QueryRephraserSpec): + Query rephraser specification. + """ + + class QueryClassificationSpec(proto.Message): + r"""Query classification specification. + + Attributes: + types (MutableSequence[google.cloud.discoveryengine_v1beta.types.AnswerQueryRequest.QueryUnderstandingSpec.QueryClassificationSpec.Type]): + Enabled query classification types. + """ + + class Type(proto.Enum): + r"""Query classification types. + + Values: + TYPE_UNSPECIFIED (0): + Unspecified query classification type. + ADVERSARIAL_QUERY (1): + Adversarial query classification type. + NON_ANSWER_SEEKING_QUERY (2): + Non-answer-seeking query classification type. + """ + TYPE_UNSPECIFIED = 0 + ADVERSARIAL_QUERY = 1 + NON_ANSWER_SEEKING_QUERY = 2 + + types: MutableSequence[ + "AnswerQueryRequest.QueryUnderstandingSpec.QueryClassificationSpec.Type" + ] = proto.RepeatedField( + proto.ENUM, + number=1, + enum="AnswerQueryRequest.QueryUnderstandingSpec.QueryClassificationSpec.Type", + ) + + class QueryRephraserSpec(proto.Message): + r"""Query rephraser specification. + + Attributes: + disable (bool): + Disable query rephraser. + max_rephrase_steps (int): + Max rephrase steps. + The max number is 10 steps. + If not set or set to < 1, it will be set to 1 by + default. + """ + + disable: bool = proto.Field( + proto.BOOL, + number=1, + ) + max_rephrase_steps: int = proto.Field( + proto.INT32, + number=2, + ) + + query_classification_spec: "AnswerQueryRequest.QueryUnderstandingSpec.QueryClassificationSpec" = proto.Field( + proto.MESSAGE, + number=1, + message="AnswerQueryRequest.QueryUnderstandingSpec.QueryClassificationSpec", + ) + query_rephraser_spec: "AnswerQueryRequest.QueryUnderstandingSpec.QueryRephraserSpec" = proto.Field( + proto.MESSAGE, + number=2, + message="AnswerQueryRequest.QueryUnderstandingSpec.QueryRephraserSpec", + ) + + serving_config: str = proto.Field( + proto.STRING, + number=1, + ) + query: gcd_session.Query = proto.Field( + proto.MESSAGE, + number=2, + message=gcd_session.Query, + ) + session: str = proto.Field( + proto.STRING, + number=3, + ) + safety_spec: SafetySpec = proto.Field( + proto.MESSAGE, + number=4, + message=SafetySpec, + ) + related_questions_spec: RelatedQuestionsSpec = proto.Field( + proto.MESSAGE, + number=5, + message=RelatedQuestionsSpec, + ) + answer_generation_spec: AnswerGenerationSpec = proto.Field( + proto.MESSAGE, + number=7, + message=AnswerGenerationSpec, + ) + search_spec: SearchSpec = proto.Field( + proto.MESSAGE, + number=8, + message=SearchSpec, + ) + query_understanding_spec: QueryUnderstandingSpec = proto.Field( + proto.MESSAGE, + number=9, + message=QueryUnderstandingSpec, + ) + asynchronous_mode: bool = proto.Field( + proto.BOOL, + number=10, + ) + user_pseudo_id: str = proto.Field( + proto.STRING, + number=12, + ) + + +class AnswerQueryResponse(proto.Message): + r"""Response message for + [ConversationalSearchService.AnswerQuery][google.cloud.discoveryengine.v1beta.ConversationalSearchService.AnswerQuery] + method. + + Attributes: + answer (google.cloud.discoveryengine_v1beta.types.Answer): + Answer resource object. If + [AnswerQueryRequest.StepSpec.max_step_count][] is greater + than 1, use + [Answer.name][google.cloud.discoveryengine.v1beta.Answer.name] + to fetch answer information using + [ConversationalSearchService.GetAnswer][google.cloud.discoveryengine.v1beta.ConversationalSearchService.GetAnswer] + API. + session (google.cloud.discoveryengine_v1beta.types.Session): + Session resource object. It will be only available when + session field is set and valid in the + [AnswerQueryRequest][google.cloud.discoveryengine.v1beta.AnswerQueryRequest] + request. + """ + + answer: gcd_answer.Answer = proto.Field( + proto.MESSAGE, + number=1, + message=gcd_answer.Answer, + ) + session: gcd_session.Session = proto.Field( + proto.MESSAGE, + number=2, + message=gcd_session.Session, + ) + + +class GetAnswerRequest(proto.Message): + r"""Request for GetAnswer method. + + Attributes: + name (str): + Required. The resource name of the Answer to get. Format: + ``projects/{project_number}/locations/{location_id}/collections/{collection}/engines/{engine_id}/sessions/{session_id}/answers/{answer_id}`` + """ + + name: str = proto.Field( + proto.STRING, + number=1, + ) + + +class CreateSessionRequest(proto.Message): + r"""Request for CreateSession method. + + Attributes: + parent (str): + Required. Full resource name of parent data store. Format: + ``projects/{project_number}/locations/{location_id}/collections/{collection}/dataStores/{data_store_id}`` + session (google.cloud.discoveryengine_v1beta.types.Session): + Required. The session to create. + """ + + parent: str = proto.Field( + proto.STRING, + number=1, + ) + session: gcd_session.Session = proto.Field( + proto.MESSAGE, + number=2, + message=gcd_session.Session, + ) + + +class UpdateSessionRequest(proto.Message): + r"""Request for UpdateSession method. + + Attributes: + session (google.cloud.discoveryengine_v1beta.types.Session): + Required. The Session to update. + update_mask (google.protobuf.field_mask_pb2.FieldMask): + Indicates which fields in the provided + [Session][google.cloud.discoveryengine.v1beta.Session] to + update. The following are NOT supported: + + - [Session.name][google.cloud.discoveryengine.v1beta.Session.name] + + If not set or empty, all supported fields are updated. + """ + + session: gcd_session.Session = proto.Field( + proto.MESSAGE, + number=1, + message=gcd_session.Session, + ) + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=2, + message=field_mask_pb2.FieldMask, + ) + + +class DeleteSessionRequest(proto.Message): + r"""Request for DeleteSession method. + + Attributes: + name (str): + Required. The resource name of the Session to delete. + Format: + ``projects/{project_number}/locations/{location_id}/collections/{collection}/dataStores/{data_store_id}/sessions/{session_id}`` + """ + + name: str = proto.Field( + proto.STRING, + number=1, + ) + + +class GetSessionRequest(proto.Message): + r"""Request for GetSession method. + + Attributes: + name (str): + Required. The resource name of the Session to get. Format: + ``projects/{project_number}/locations/{location_id}/collections/{collection}/dataStores/{data_store_id}/sessions/{session_id}`` + """ + + name: str = proto.Field( + proto.STRING, + number=1, + ) + + +class ListSessionsRequest(proto.Message): + r"""Request for ListSessions method. + + Attributes: + parent (str): + Required. The data store resource name. Format: + ``projects/{project_number}/locations/{location_id}/collections/{collection}/dataStores/{data_store_id}`` + page_size (int): + Maximum number of results to return. If + unspecified, defaults to 50. Max allowed value + is 1000. + page_token (str): + A page token, received from a previous ``ListSessions`` + call. Provide this to retrieve the subsequent page. + filter (str): + A filter to apply on the list results. The supported + features are: user_pseudo_id, state. + + Example: "user_pseudo_id = some_id". + order_by (str): + A comma-separated list of fields to order by, sorted in + ascending order. Use "desc" after a field name for + descending. Supported fields: + + - ``update_time`` + - ``create_time`` + - ``session_name`` + + Example: "update_time desc" "create_time". + """ + + parent: str = proto.Field( + proto.STRING, + number=1, + ) + page_size: int = proto.Field( + proto.INT32, + number=2, + ) + page_token: str = proto.Field( + proto.STRING, + number=3, + ) + filter: str = proto.Field( + proto.STRING, + number=4, + ) + order_by: str = proto.Field( + proto.STRING, + number=5, + ) + + +class ListSessionsResponse(proto.Message): + r"""Response for ListSessions method. + + Attributes: + sessions (MutableSequence[google.cloud.discoveryengine_v1beta.types.Session]): + All the Sessions for a given data store. + next_page_token (str): + Pagination token, if not returned indicates + the last page. + """ + + @property + def raw_page(self): + return self + + sessions: MutableSequence[gcd_session.Session] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message=gcd_session.Session, + ) + next_page_token: str = proto.Field( + proto.STRING, + number=2, + ) + + __all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/document_processing_config.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/document_processing_config.py index 24d735ea6873..265d0661748d 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/document_processing_config.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/document_processing_config.py @@ -91,12 +91,9 @@ class OcrParsingConfig(proto.Message): Attributes: enhanced_document_elements (MutableSequence[str]): - Apply additional enhanced OCR processing to a list of - document elements. - - Supported values: - - - ``table``: advanced table parsing model. + [DEPRECATED] This field is deprecated. To use the additional + enhanced document elements processing, please switch to + ``layout_parsing_config``. use_native_text (bool): If true, will use native text instead of OCR text on pages containing native text. diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/document_service.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/document_service.py index 3104b312c21e..608caf7bd441 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/document_service.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/document_service.py @@ -17,6 +17,7 @@ from typing import MutableMapping, MutableSequence +from google.protobuf import field_mask_pb2 # type: ignore import proto # type: ignore from google.cloud.discoveryengine_v1beta.types import document as gcd_document @@ -220,6 +221,10 @@ class UpdateDocumentRequest(proto.Message): not found, a new [Document][google.cloud.discoveryengine.v1beta.Document] will be created. + update_mask (google.protobuf.field_mask_pb2.FieldMask): + Indicates which fields in the provided + imported 'document' to update. If not set, will + by default update all fields. """ document: gcd_document.Document = proto.Field( @@ -231,6 +236,11 @@ class UpdateDocumentRequest(proto.Message): proto.BOOL, number=2, ) + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=3, + message=field_mask_pb2.FieldMask, + ) class DeleteDocumentRequest(proto.Message): diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/engine.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/engine.py index 6c3b32b16cec..85b3133d0b8e 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/engine.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/engine.py @@ -131,7 +131,7 @@ class SearchEngineConfig(proto.Message): The search feature tier of this engine. Different tiers might have different pricing. To learn more, - please check the pricing documentation. + check the pricing documentation. Defaults to [SearchTier.SEARCH_TIER_STANDARD][google.cloud.discoveryengine.v1beta.SearchTier.SEARCH_TIER_STANDARD] @@ -181,7 +181,7 @@ class ChatEngineConfig(proto.Message): [EngineService.GetEngine][google.cloud.discoveryengine.v1beta.EngineService.GetEngine] or [EngineService.ListEngines][google.cloud.discoveryengine.v1beta.EngineService.ListEngines] - API after engine creation. Please use + API after engine creation. Use [ChatEngineMetadata.dialogflow_agent][google.cloud.discoveryengine.v1beta.Engine.ChatEngineMetadata.dialogflow_agent] for actual agent association after Engine is created. """ diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/engine_service.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/engine_service.py index 647f4e606032..290ed0392a6b 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/engine_service.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/engine_service.py @@ -34,6 +34,11 @@ "ListEnginesRequest", "ListEnginesResponse", "UpdateEngineRequest", + "PauseEngineRequest", + "ResumeEngineRequest", + "TuneEngineRequest", + "TuneEngineMetadata", + "TuneEngineResponse", }, ) @@ -280,4 +285,70 @@ class UpdateEngineRequest(proto.Message): ) +class PauseEngineRequest(proto.Message): + r"""Request for pausing training of an engine. + + Attributes: + name (str): + Required. The name of the engine to pause. Format: + ``projects/{project_number}/locations/{location_id}/collections/{collection_id}/engines/{engine_id}`` + """ + + name: str = proto.Field( + proto.STRING, + number=1, + ) + + +class ResumeEngineRequest(proto.Message): + r"""Request for resuming training of an engine. + + Attributes: + name (str): + Required. The name of the engine to resume. Format: + ``projects/{project_number}/locations/{location_id}/collections/{collection_id}/engines/{engine_id}`` + """ + + name: str = proto.Field( + proto.STRING, + number=1, + ) + + +class TuneEngineRequest(proto.Message): + r"""Request to manually start a tuning process now (instead of + waiting for the periodically scheduled tuning to happen). + + Attributes: + name (str): + Required. The resource name of the engine to tune. Format: + ``projects/{project_number}/locations/{location_id}/collections/{collection_id}/engines/{engine_id}`` + """ + + name: str = proto.Field( + proto.STRING, + number=1, + ) + + +class TuneEngineMetadata(proto.Message): + r"""Metadata associated with a tune operation. + + Attributes: + engine (str): + Required. The resource name of the engine that this tune + applies to. Format: + ``projects/{project_number}/locations/{location_id}/collections/{collection_id}/engines/{engine_id}`` + """ + + engine: str = proto.Field( + proto.STRING, + number=1, + ) + + +class TuneEngineResponse(proto.Message): + r"""Response associated with a tune operation.""" + + __all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/grounded_generation_service.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/grounded_generation_service.py new file mode 100644 index 000000000000..d88ba576cd47 --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/grounded_generation_service.py @@ -0,0 +1,186 @@ +# -*- 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 + +from google.cloud.discoveryengine_v1beta.types import grounding + +__protobuf__ = proto.module( + package="google.cloud.discoveryengine.v1beta", + manifest={ + "CheckGroundingSpec", + "CheckGroundingRequest", + "CheckGroundingResponse", + }, +) + + +class CheckGroundingSpec(proto.Message): + r"""Specification for the grounding check. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + citation_threshold (float): + The threshold (in [0,1]) used for determining whether a fact + must be cited for a claim in the answer candidate. Choosing + a higher threshold will lead to fewer but very strong + citations, while choosing a lower threshold may lead to more + but somewhat weaker citations. If unset, the threshold will + default to 0.6. + + This field is a member of `oneof`_ ``_citation_threshold``. + """ + + citation_threshold: float = proto.Field( + proto.DOUBLE, + number=1, + optional=True, + ) + + +class CheckGroundingRequest(proto.Message): + r"""Request message for + [GroundedGenerationService.CheckGrounding][google.cloud.discoveryengine.v1beta.GroundedGenerationService.CheckGrounding] + method. + + Attributes: + grounding_config (str): + Required. The resource name of the grounding config, such as + ``projects/*/locations/global/groundingConfigs/default_grounding_config``. + answer_candidate (str): + Answer candidate to check. + facts (MutableSequence[google.cloud.discoveryengine_v1beta.types.GroundingFact]): + List of facts for the grounding check. + We support up to 200 facts. + grounding_spec (google.cloud.discoveryengine_v1beta.types.CheckGroundingSpec): + Configuration of the grounding check. + """ + + grounding_config: str = proto.Field( + proto.STRING, + number=1, + ) + answer_candidate: str = proto.Field( + proto.STRING, + number=2, + ) + facts: MutableSequence[grounding.GroundingFact] = proto.RepeatedField( + proto.MESSAGE, + number=3, + message=grounding.GroundingFact, + ) + grounding_spec: "CheckGroundingSpec" = proto.Field( + proto.MESSAGE, + number=4, + message="CheckGroundingSpec", + ) + + +class CheckGroundingResponse(proto.Message): + r"""Response message for the + [GroundedGenerationService.CheckGrounding][google.cloud.discoveryengine.v1beta.GroundedGenerationService.CheckGrounding] + method. + + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + support_score (float): + The support score for the input answer + candidate. Higher the score, higher is the + fraction of claims that are supported by the + provided facts. This is always set when a + response is returned. + + This field is a member of `oneof`_ ``_support_score``. + cited_chunks (MutableSequence[google.cloud.discoveryengine_v1beta.types.FactChunk]): + List of facts cited across all claims in the + answer candidate. These are derived from the + facts supplied in the request. + claims (MutableSequence[google.cloud.discoveryengine_v1beta.types.CheckGroundingResponse.Claim]): + Claim texts and citation info across all + claims in the answer candidate. + """ + + class Claim(proto.Message): + r"""Text and citation info for a claim in the answer candidate. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + start_pos (int): + Position indicating the start of the claim in + the answer candidate, measured in bytes. + + This field is a member of `oneof`_ ``_start_pos``. + end_pos (int): + Position indicating the end of the claim in + the answer candidate, exclusive. + + This field is a member of `oneof`_ ``_end_pos``. + claim_text (str): + Text for the claim in the answer candidate. + Always provided regardless of whether citations + or anti-citations are found. + citation_indices (MutableSequence[int]): + A list of indices (into 'cited_chunks') specifying the + citations associated with the claim. For instance [1,3,4] + means that cited_chunks[1], cited_chunks[3], cited_chunks[4] + are the facts cited supporting for the claim. A citation to + a fact indicates that the claim is supported by the fact. + """ + + start_pos: int = proto.Field( + proto.INT32, + number=1, + optional=True, + ) + end_pos: int = proto.Field( + proto.INT32, + number=2, + optional=True, + ) + claim_text: str = proto.Field( + proto.STRING, + number=3, + ) + citation_indices: MutableSequence[int] = proto.RepeatedField( + proto.INT32, + number=4, + ) + + support_score: float = proto.Field( + proto.FLOAT, + number=1, + optional=True, + ) + cited_chunks: MutableSequence[grounding.FactChunk] = proto.RepeatedField( + proto.MESSAGE, + number=3, + message=grounding.FactChunk, + ) + claims: MutableSequence[Claim] = proto.RepeatedField( + proto.MESSAGE, + number=4, + message=Claim, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/grounding.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/grounding.py new file mode 100644 index 000000000000..0750fbfc2414 --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/grounding.py @@ -0,0 +1,89 @@ +# -*- 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.discoveryengine.v1beta", + manifest={ + "GroundingFact", + "FactChunk", + }, +) + + +class GroundingFact(proto.Message): + r"""Grounding Fact. + + Attributes: + fact_text (str): + Text content of the fact. Can be at most 10K + characters long. + attributes (MutableMapping[str, str]): + Attributes associated with the fact. Common attributes + include ``source`` (indicating where the fact was sourced + from), ``author`` (indicating the author of the fact), and + so on. + """ + + fact_text: str = proto.Field( + proto.STRING, + number=1, + ) + attributes: MutableMapping[str, str] = proto.MapField( + proto.STRING, + proto.STRING, + number=2, + ) + + +class FactChunk(proto.Message): + r"""Fact Chunk. + + Attributes: + chunk_text (str): + Text content of the fact chunk. Can be at + most 10K characters long. + source (str): + Source from which this fact chunk was + retrieved. If it was retrieved from the + GroundingFacts provided in the request then this + field will contain the index of the specific + fact from which this chunk was retrieved. + source_metadata (MutableMapping[str, str]): + More fine-grained information for the source + reference. + """ + + chunk_text: str = proto.Field( + proto.STRING, + number=1, + ) + source: str = proto.Field( + proto.STRING, + number=2, + ) + source_metadata: MutableMapping[str, str] = proto.MapField( + proto.STRING, + proto.STRING, + number=3, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/import_config.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/import_config.py index fcca4ae92e55..66c6771b4d2a 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/import_config.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/import_config.py @@ -17,6 +17,7 @@ from typing import MutableMapping, MutableSequence +from google.protobuf import field_mask_pb2 # type: ignore from google.protobuf import timestamp_pb2 # type: ignore from google.rpc import status_pb2 # type: ignore from google.type import date_pb2 # type: ignore @@ -29,6 +30,12 @@ manifest={ "GcsSource", "BigQuerySource", + "SpannerSource", + "BigtableOptions", + "BigtableSource", + "FhirStoreSource", + "CloudSqlSource", + "FirestoreSource", "ImportErrorConfig", "ImportUserEventsRequest", "ImportUserEventsResponse", @@ -73,11 +80,13 @@ class GcsSource(proto.Message): - ``custom``: One custom data JSON per row in arbitrary format that conforms to the defined [Schema][google.cloud.discoveryengine.v1beta.Schema] of - the data store. This can only be used by Gen App Builder. + the data store. This can only be used by the GENERIC Data + Store vertical. - ``csv``: A CSV file with header conforming to the defined [Schema][google.cloud.discoveryengine.v1beta.Schema] of the data store. Each entry after the header is imported - as a Document. This can only be used by Gen App Builder. + as a Document. This can only be used by the GENERIC Data + Store vertical. Supported values for user even imports: @@ -147,7 +156,8 @@ class BigQuerySource(proto.Message): - ``custom``: One custom data per row in arbitrary format that conforms to the defined [Schema][google.cloud.discoveryengine.v1beta.Schema] of - the data store. This can only be used by Gen App Builder. + the data store. This can only be used by the GENERIC Data + Store vertical. """ partition_date: date_pb2.Date = proto.Field( @@ -178,6 +188,402 @@ class BigQuerySource(proto.Message): ) +class SpannerSource(proto.Message): + r"""The Spanner source for importing data + + Attributes: + project_id (str): + The project ID that the Spanner source is in + with a length limit of 128 characters. If not + specified, inherits the project ID from the + parent request. + instance_id (str): + Required. The instance ID of the source + Spanner table. + database_id (str): + Required. The database ID of the source + Spanner table. + table_id (str): + Required. The table name of the Spanner + database that needs to be imported. + enable_data_boost (bool): + Whether to apply data boost on Spanner export. Enabling this + option will incur additional cost. More info can be found + `here `__. + """ + + project_id: str = proto.Field( + proto.STRING, + number=1, + ) + instance_id: str = proto.Field( + proto.STRING, + number=2, + ) + database_id: str = proto.Field( + proto.STRING, + number=3, + ) + table_id: str = proto.Field( + proto.STRING, + number=4, + ) + enable_data_boost: bool = proto.Field( + proto.BOOL, + number=5, + ) + + +class BigtableOptions(proto.Message): + r"""The Bigtable Options object that contains information to + support the import. + + Attributes: + key_field_name (str): + The field name used for saving row key value in the + document. The name has to match the pattern + ``[a-zA-Z0-9][a-zA-Z0-9-_]*``. + families (MutableMapping[str, google.cloud.discoveryengine_v1beta.types.BigtableOptions.BigtableColumnFamily]): + The mapping from family names to an object + that contains column families level information + for the given column family. If a family is not + present in this map it will be ignored. + """ + + class Type(proto.Enum): + r"""The type of values in a Bigtable column or column family. The values + are expected to be encoded using `HBase + Bytes.toBytes `__ + function when the encoding value is set to ``BINARY``. + + Values: + TYPE_UNSPECIFIED (0): + The type is unspecified. + STRING (1): + String type. + NUMBER (2): + Numerical type. + INTEGER (3): + Integer type. + VAR_INTEGER (4): + Variable length integer type. + BIG_NUMERIC (5): + BigDecimal type. + BOOLEAN (6): + Boolean type. + JSON (7): + JSON type. + """ + TYPE_UNSPECIFIED = 0 + STRING = 1 + NUMBER = 2 + INTEGER = 3 + VAR_INTEGER = 4 + BIG_NUMERIC = 5 + BOOLEAN = 6 + JSON = 7 + + class Encoding(proto.Enum): + r"""The encoding mode of a Bigtable column or column family. + + Values: + ENCODING_UNSPECIFIED (0): + The encoding is unspecified. + TEXT (1): + Text encoding. + BINARY (2): + Binary encoding. + """ + ENCODING_UNSPECIFIED = 0 + TEXT = 1 + BINARY = 2 + + class BigtableColumnFamily(proto.Message): + r"""The column family of the Bigtable. + + Attributes: + field_name (str): + The field name to use for this column family in the + document. The name has to match the pattern + ``[a-zA-Z0-9][a-zA-Z0-9-_]*``. If not set, it is parsed from + the family name with best effort. However, due to different + naming patterns, field name collisions could happen, where + parsing behavior is undefined. + encoding (google.cloud.discoveryengine_v1beta.types.BigtableOptions.Encoding): + The encoding mode of the values when the type is not STRING. + Acceptable encoding values are: + + - ``TEXT``: indicates values are alphanumeric text strings. + - ``BINARY``: indicates values are encoded using + ``HBase Bytes.toBytes`` family of functions. This can be + overridden for a specific column by listing that column + in ``columns`` and specifying an encoding for it. + type_ (google.cloud.discoveryengine_v1beta.types.BigtableOptions.Type): + The type of values in this column family. The values are + expected to be encoded using ``HBase Bytes.toBytes`` + function when the encoding value is set to ``BINARY``. + columns (MutableSequence[google.cloud.discoveryengine_v1beta.types.BigtableOptions.BigtableColumn]): + The list of objects that contains column + level information for each column. If a column + is not present in this list it will be ignored. + """ + + field_name: str = proto.Field( + proto.STRING, + number=1, + ) + encoding: "BigtableOptions.Encoding" = proto.Field( + proto.ENUM, + number=2, + enum="BigtableOptions.Encoding", + ) + type_: "BigtableOptions.Type" = proto.Field( + proto.ENUM, + number=3, + enum="BigtableOptions.Type", + ) + columns: MutableSequence[ + "BigtableOptions.BigtableColumn" + ] = proto.RepeatedField( + proto.MESSAGE, + number=4, + message="BigtableOptions.BigtableColumn", + ) + + class BigtableColumn(proto.Message): + r"""The column of the Bigtable. + + Attributes: + qualifier (bytes): + Required. Qualifier of the column. If it + cannot be decoded with utf-8, use a base-64 + encoded string instead. + field_name (str): + The field name to use for this column in the document. The + name has to match the pattern ``[a-zA-Z0-9][a-zA-Z0-9-_]*``. + If not set, it is parsed from the qualifier bytes with best + effort. However, due to different naming patterns, field + name collisions could happen, where parsing behavior is + undefined. + encoding (google.cloud.discoveryengine_v1beta.types.BigtableOptions.Encoding): + The encoding mode of the values when the type is not + ``STRING``. Acceptable encoding values are: + + - ``TEXT``: indicates values are alphanumeric text strings. + - ``BINARY``: indicates values are encoded using + ``HBase Bytes.toBytes`` family of functions. This can be + overridden for a specific column by listing that column + in ``columns`` and specifying an encoding for it. + type_ (google.cloud.discoveryengine_v1beta.types.BigtableOptions.Type): + The type of values in this column family. The values are + expected to be encoded using ``HBase Bytes.toBytes`` + function when the encoding value is set to ``BINARY``. + """ + + qualifier: bytes = proto.Field( + proto.BYTES, + number=1, + ) + field_name: str = proto.Field( + proto.STRING, + number=2, + ) + encoding: "BigtableOptions.Encoding" = proto.Field( + proto.ENUM, + number=3, + enum="BigtableOptions.Encoding", + ) + type_: "BigtableOptions.Type" = proto.Field( + proto.ENUM, + number=4, + enum="BigtableOptions.Type", + ) + + key_field_name: str = proto.Field( + proto.STRING, + number=1, + ) + families: MutableMapping[str, BigtableColumnFamily] = proto.MapField( + proto.STRING, + proto.MESSAGE, + number=2, + message=BigtableColumnFamily, + ) + + +class BigtableSource(proto.Message): + r"""The Cloud Bigtable source for importing data. + + Attributes: + project_id (str): + The project ID that the Bigtable source is in + with a length limit of 128 characters. If not + specified, inherits the project ID from the + parent request. + instance_id (str): + Required. The instance ID of the Cloud + Bigtable that needs to be imported. + table_id (str): + Required. The table ID of the Cloud Bigtable + that needs to be imported. + bigtable_options (google.cloud.discoveryengine_v1beta.types.BigtableOptions): + Required. Bigtable options that contains + information needed when parsing data into typed + structures. For example, column type + annotations. + """ + + project_id: str = proto.Field( + proto.STRING, + number=1, + ) + instance_id: str = proto.Field( + proto.STRING, + number=2, + ) + table_id: str = proto.Field( + proto.STRING, + number=3, + ) + bigtable_options: "BigtableOptions" = proto.Field( + proto.MESSAGE, + number=4, + message="BigtableOptions", + ) + + +class FhirStoreSource(proto.Message): + r"""Cloud FhirStore source import data from. + + Attributes: + fhir_store (str): + Required. The full resource name of the FHIR store to import + data from, in the format of + ``projects/{project}/locations/{location}/datasets/{dataset}/fhirStores/{fhir_store}``. + gcs_staging_dir (str): + Intermediate Cloud Storage directory used for + the import with a length limit of 2,000 + characters. Can be specified if one wants to + have the FhirStore export to a specific Cloud + Storage directory. + """ + + fhir_store: str = proto.Field( + proto.STRING, + number=1, + ) + gcs_staging_dir: str = proto.Field( + proto.STRING, + number=2, + ) + + +class CloudSqlSource(proto.Message): + r"""Cloud SQL source import data from. + + Attributes: + project_id (str): + The project ID that the Cloud SQL source is + in with a length limit of 128 characters. If not + specified, inherits the project ID from the + parent request. + instance_id (str): + Required. The Cloud SQL instance to copy the + data from with a length limit of 256 characters. + database_id (str): + Required. The Cloud SQL database to copy the + data from with a length limit of 256 characters. + table_id (str): + Required. The Cloud SQL table to copy the + data from with a length limit of 256 characters. + gcs_staging_dir (str): + Intermediate Cloud Storage directory used for + the import with a length limit of 2,000 + characters. Can be specified if one wants to + have the Cloud SQL export to a specific Cloud + Storage directory. + + Ensure that the Cloud SQL service account has + the necessary Cloud Storage Admin permissions to + access the specified Cloud Storage directory. + offload (bool): + Option for serverless export. Enabling this option will + incur additional cost. More info can be found + `here `__. + """ + + project_id: str = proto.Field( + proto.STRING, + number=1, + ) + instance_id: str = proto.Field( + proto.STRING, + number=2, + ) + database_id: str = proto.Field( + proto.STRING, + number=3, + ) + table_id: str = proto.Field( + proto.STRING, + number=4, + ) + gcs_staging_dir: str = proto.Field( + proto.STRING, + number=5, + ) + offload: bool = proto.Field( + proto.BOOL, + number=6, + ) + + +class FirestoreSource(proto.Message): + r"""Firestore source import data from. + + Attributes: + project_id (str): + The project ID that the Cloud SQL source is + in with a length limit of 128 characters. If not + specified, inherits the project ID from the + parent request. + database_id (str): + Required. The Firestore database to copy the + data from with a length limit of 256 characters. + collection_id (str): + Required. The Firestore collection to copy + the data from with a length limit of 1,500 + characters. + gcs_staging_dir (str): + Intermediate Cloud Storage directory used for + the import with a length limit of 2,000 + characters. Can be specified if one wants to + have the Firestore export to a specific Cloud + Storage directory. + + Ensure that the Firestore service account has + the necessary Cloud Storage Admin permissions to + access the specified Cloud Storage directory. + """ + + project_id: str = proto.Field( + proto.STRING, + number=1, + ) + database_id: str = proto.Field( + proto.STRING, + number=2, + ) + collection_id: str = proto.Field( + proto.STRING, + number=3, + ) + gcs_staging_dir: str = proto.Field( + proto.STRING, + number=4, + ) + + class ImportErrorConfig(proto.Message): r"""Configuration of destination for Import related errors. @@ -376,6 +782,8 @@ class ImportDocumentsMetadata(proto.Message): failure_count (int): Count of entries that encountered errors while processing. + total_count (int): + Total count of entries that were processed. """ create_time: timestamp_pb2.Timestamp = proto.Field( @@ -396,6 +804,10 @@ class ImportDocumentsMetadata(proto.Message): proto.INT64, number=4, ) + total_count: int = proto.Field( + proto.INT64, + number=5, + ) class ImportDocumentsRequest(proto.Message): @@ -421,6 +833,26 @@ class ImportDocumentsRequest(proto.Message): bigquery_source (google.cloud.discoveryengine_v1beta.types.BigQuerySource): BigQuery input source. + This field is a member of `oneof`_ ``source``. + fhir_store_source (google.cloud.discoveryengine_v1beta.types.FhirStoreSource): + FhirStore input source. + + This field is a member of `oneof`_ ``source``. + spanner_source (google.cloud.discoveryengine_v1beta.types.SpannerSource): + Spanner input source. + + This field is a member of `oneof`_ ``source``. + cloud_sql_source (google.cloud.discoveryengine_v1beta.types.CloudSqlSource): + Cloud SQL input source. + + This field is a member of `oneof`_ ``source``. + firestore_source (google.cloud.discoveryengine_v1beta.types.FirestoreSource): + Firestore input source. + + This field is a member of `oneof`_ ``source``. + bigtable_source (google.cloud.discoveryengine_v1beta.types.BigtableSource): + Cloud Bigtable input source. + This field is a member of `oneof`_ ``source``. parent (str): Required. The parent branch resource name, such as @@ -433,6 +865,10 @@ class ImportDocumentsRequest(proto.Message): The mode of reconciliation between existing documents and the documents to be imported. Defaults to [ReconciliationMode.INCREMENTAL][google.cloud.discoveryengine.v1beta.ImportDocumentsRequest.ReconciliationMode.INCREMENTAL]. + update_mask (google.protobuf.field_mask_pb2.FieldMask): + Indicates which fields in the provided + imported documents to update. If not set, the + default is to update all fields. auto_generate_ids (bool): Whether to automatically generate IDs for the documents if absent. @@ -450,52 +886,61 @@ class ImportDocumentsRequest(proto.Message): [id_field][google.cloud.discoveryengine.v1beta.ImportDocumentsRequest.id_field], otherwise, documents without IDs fail to be imported. - Only set this field when using - [GcsSource][google.cloud.discoveryengine.v1beta.GcsSource] - or - [BigQuerySource][google.cloud.discoveryengine.v1beta.BigQuerySource], - and when - [GcsSource.data_schema][google.cloud.discoveryengine.v1beta.GcsSource.data_schema] - or - [BigQuerySource.data_schema][google.cloud.discoveryengine.v1beta.BigQuerySource.data_schema] - is ``custom`` or ``csv``. Otherwise, an INVALID_ARGUMENT - error is thrown. + Supported data sources: + + - [GcsSource][google.cloud.discoveryengine.v1beta.GcsSource]. + [GcsSource.data_schema][google.cloud.discoveryengine.v1beta.GcsSource.data_schema] + must be ``custom`` or ``csv``. Otherwise, an + INVALID_ARGUMENT error is thrown. + - [BigQuerySource][google.cloud.discoveryengine.v1beta.BigQuerySource]. + [BigQuerySource.data_schema][google.cloud.discoveryengine.v1beta.BigQuerySource.data_schema] + must be ``custom`` or ``csv``. Otherwise, an + INVALID_ARGUMENT error is thrown. + - [SpannerSource][google.cloud.discoveryengine.v1beta.SpannerSource]. + - [CloudSqlSource][google.cloud.discoveryengine.v1beta.CloudSqlSource]. + - [FirestoreSource][google.cloud.discoveryengine.v1beta.FirestoreSource]. + - [BigtableSource][google.cloud.discoveryengine.v1beta.BigtableSource]. id_field (str): - The field in the Cloud Storage and BigQuery sources that - indicates the unique IDs of the documents. + The field indicates the ID field or column to be used as + unique IDs of the documents. For [GcsSource][google.cloud.discoveryengine.v1beta.GcsSource] it is the key of the JSON field. For instance, ``my_id`` for - JSON ``{"my_id": "some_uuid"}``. For - [BigQuerySource][google.cloud.discoveryengine.v1beta.BigQuerySource] - it is the column name of the BigQuery table where the unique - ids are stored. + JSON ``{"my_id": "some_uuid"}``. For others, it may be the + column name of the table where the unique ids are stored. - The values of the JSON field or the BigQuery column are used - as the + The values of the JSON field or the table column are used as + the [Document.id][google.cloud.discoveryengine.v1beta.Document.id]s. - The JSON field or the BigQuery column must be of string - type, and the values must be set as valid strings conform to + The JSON field or the table column must be of string type, + and the values must be set as valid strings conform to `RFC-1034 `__ with 1-63 characters. Otherwise, documents without valid IDs fail to be imported. - Only set this field when using - [GcsSource][google.cloud.discoveryengine.v1beta.GcsSource] - or - [BigQuerySource][google.cloud.discoveryengine.v1beta.BigQuerySource], - and when - [GcsSource.data_schema][google.cloud.discoveryengine.v1beta.GcsSource.data_schema] - or - [BigQuerySource.data_schema][google.cloud.discoveryengine.v1beta.BigQuerySource.data_schema] - is ``custom``. And only set this field when + Only set this field when [auto_generate_ids][google.cloud.discoveryengine.v1beta.ImportDocumentsRequest.auto_generate_ids] is unset or set as ``false``. Otherwise, an INVALID_ARGUMENT error is thrown. If it is unset, a default value ``_id`` is used when importing from the allowed data sources. + + Supported data sources: + + - [GcsSource][google.cloud.discoveryengine.v1beta.GcsSource]. + [GcsSource.data_schema][google.cloud.discoveryengine.v1beta.GcsSource.data_schema] + must be ``custom`` or ``csv``. Otherwise, an + INVALID_ARGUMENT error is thrown. + - [BigQuerySource][google.cloud.discoveryengine.v1beta.BigQuerySource]. + [BigQuerySource.data_schema][google.cloud.discoveryengine.v1beta.BigQuerySource.data_schema] + must be ``custom`` or ``csv``. Otherwise, an + INVALID_ARGUMENT error is thrown. + - [SpannerSource][google.cloud.discoveryengine.v1beta.SpannerSource]. + - [CloudSqlSource][google.cloud.discoveryengine.v1beta.CloudSqlSource]. + - [FirestoreSource][google.cloud.discoveryengine.v1beta.FirestoreSource]. + - [BigtableSource][google.cloud.discoveryengine.v1beta.BigtableSource]. """ class ReconciliationMode(proto.Enum): @@ -554,6 +999,36 @@ class InlineSource(proto.Message): oneof="source", message="BigQuerySource", ) + fhir_store_source: "FhirStoreSource" = proto.Field( + proto.MESSAGE, + number=10, + oneof="source", + message="FhirStoreSource", + ) + spanner_source: "SpannerSource" = proto.Field( + proto.MESSAGE, + number=11, + oneof="source", + message="SpannerSource", + ) + cloud_sql_source: "CloudSqlSource" = proto.Field( + proto.MESSAGE, + number=12, + oneof="source", + message="CloudSqlSource", + ) + firestore_source: "FirestoreSource" = proto.Field( + proto.MESSAGE, + number=13, + oneof="source", + message="FirestoreSource", + ) + bigtable_source: "BigtableSource" = proto.Field( + proto.MESSAGE, + number=15, + oneof="source", + message="BigtableSource", + ) parent: str = proto.Field( proto.STRING, number=1, @@ -568,6 +1043,11 @@ class InlineSource(proto.Message): number=6, enum=ReconciliationMode, ) + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=7, + message=field_mask_pb2.FieldMask, + ) auto_generate_ids: bool = proto.Field( proto.BOOL, number=8, diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/rank_service.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/rank_service.py new file mode 100644 index 000000000000..c7396cf30124 --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/rank_service.py @@ -0,0 +1,152 @@ +# -*- 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.discoveryengine.v1beta", + manifest={ + "RankingRecord", + "RankRequest", + "RankResponse", + }, +) + + +class RankingRecord(proto.Message): + r"""Record message for + [RankService.Rank][google.cloud.discoveryengine.v1beta.RankService.Rank] + method. + + Attributes: + id (str): + The unique ID to represent the record. + title (str): + The title of the record. Empty by default. At least one of + [title][google.cloud.discoveryengine.v1beta.RankingRecord.title] + or + [content][google.cloud.discoveryengine.v1beta.RankingRecord.content] + should be set otherwise an INVALID_ARGUMENT error is thrown. + content (str): + The content of the record. Empty by default. At least one of + [title][google.cloud.discoveryengine.v1beta.RankingRecord.title] + or + [content][google.cloud.discoveryengine.v1beta.RankingRecord.content] + should be set otherwise an INVALID_ARGUMENT error is thrown. + score (float): + The score of this record based on the given + query and selected model. + """ + + id: str = proto.Field( + proto.STRING, + number=1, + ) + title: str = proto.Field( + proto.STRING, + number=2, + ) + content: str = proto.Field( + proto.STRING, + number=3, + ) + score: float = proto.Field( + proto.FLOAT, + number=4, + ) + + +class RankRequest(proto.Message): + r"""Request message for + [RankService.Rank][google.cloud.discoveryengine.v1beta.RankService.Rank] + method. + + Attributes: + ranking_config (str): + Required. The resource name of the rank service config, such + as + ``projects/{project_num}/locations/{location_id}/rankingConfigs/default_ranking_config``. + model (str): + The identifier of the model to use. It is one of: + + - ``semantic-ranker-512@latest``: Semantic ranking model + with maxiumn input token size 512. + + It is set to ``semantic-ranker-512@latest`` by default if + unspecified. + top_n (int): + The number of results to return. If this is + unset or no bigger than zero, returns all + results. + query (str): + The query to use. + records (MutableSequence[google.cloud.discoveryengine_v1beta.types.RankingRecord]): + Required. A list of records to rank. At most + 200 records to rank. + ignore_record_details_in_response (bool): + If true, the response will contain only + record ID and score. By default, it is false, + the response will contain record details. + """ + + ranking_config: str = proto.Field( + proto.STRING, + number=1, + ) + model: str = proto.Field( + proto.STRING, + number=2, + ) + top_n: int = proto.Field( + proto.INT32, + number=3, + ) + query: str = proto.Field( + proto.STRING, + number=4, + ) + records: MutableSequence["RankingRecord"] = proto.RepeatedField( + proto.MESSAGE, + number=5, + message="RankingRecord", + ) + ignore_record_details_in_response: bool = proto.Field( + proto.BOOL, + number=6, + ) + + +class RankResponse(proto.Message): + r"""Response message for + [RankService.Rank][google.cloud.discoveryengine.v1beta.RankService.Rank] + method. + + Attributes: + records (MutableSequence[google.cloud.discoveryengine_v1beta.types.RankingRecord]): + A list of records sorted by descending score. + """ + + records: MutableSequence["RankingRecord"] = proto.RepeatedField( + proto.MESSAGE, + number=5, + message="RankingRecord", + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/search_service.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/search_service.py index 9052829b347d..86aa2cc5ab3e 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/search_service.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/search_service.py @@ -59,9 +59,15 @@ class SearchRequest(proto.Message): page_size (int): Maximum number of [Document][google.cloud.discoveryengine.v1beta.Document]s to - return. If unspecified, defaults to a reasonable value. The - maximum allowed value is 100. Values above 100 are coerced - to 100. + return. The maximum allowed value depends on the data type. + Values above the maximum value are coerced to the maximum + value. + + - Websites with basic indexing: Default ``10``, Maximum + ``25``. + - Websites with advanced indexing: Default ``25``, Maximum + ``50``. + - Other: Default ``50``, Maximum ``100``. If this field is negative, an ``INVALID_ARGUMENT`` is returned. @@ -203,7 +209,7 @@ class SearchRequest(proto.Message): If [SearchRequest.EmbeddingSpec.EmbeddingVector.field_path][google.cloud.discoveryengine.v1beta.SearchRequest.EmbeddingSpec.EmbeddingVector.field_path] is not provided, it will use - [ServingConfig.EmbeddingConfig.field_path][]. + [ServingConfig.EmbeddingConfig.field_path][google.cloud.discoveryengine.v1beta.ServingConfig.embedding_config]. ranking_expression (str): The ranking expression controls the customized ranking on retrieval documents. This overrides @@ -523,9 +529,131 @@ class ConditionBoostSpec(proto.Message): ranking, but it is not blocked out completely. Setting to 0.0 means no boost applied. The boosting - condition is ignored. + condition is ignored. Only one of the (condition, boost) + combination or the boost_control_spec below are set. If both + are set then the global boost is ignored and the more + fine-grained boost_control_spec is applied. + boost_control_spec (google.cloud.discoveryengine_v1beta.types.SearchRequest.BoostSpec.ConditionBoostSpec.BoostControlSpec): + Complex specification for custom ranking + based on customer defined attribute value. """ + class BoostControlSpec(proto.Message): + r"""Specification for custom ranking based on customer specified + attribute value. It provides more controls for customized + ranking than the simple (condition, boost) combination above. + + Attributes: + field_name (str): + The name of the field whose value will be + used to determine the boost amount. + attribute_type (google.cloud.discoveryengine_v1beta.types.SearchRequest.BoostSpec.ConditionBoostSpec.BoostControlSpec.AttributeType): + The attribute type to be used to determine the boost amount. + The attribute value can be derived from the field value of + the specified field_name. In the case of numerical it is + straightforward i.e. attribute_value = + numerical_field_value. In the case of freshness however, + attribute_value = (time.now() - datetime_field_value). + interpolation_type (google.cloud.discoveryengine_v1beta.types.SearchRequest.BoostSpec.ConditionBoostSpec.BoostControlSpec.InterpolationType): + The interpolation type to be applied to + connect the control points listed below. + control_points (MutableSequence[google.cloud.discoveryengine_v1beta.types.SearchRequest.BoostSpec.ConditionBoostSpec.BoostControlSpec.ControlPoint]): + The control points used to define the curve. The monotonic + function (defined through the interpolation_type above) + passes through the control points listed here. + """ + + class AttributeType(proto.Enum): + r"""The attribute(or function) for which the custom ranking is to + be applied. + + Values: + ATTRIBUTE_TYPE_UNSPECIFIED (0): + Unspecified AttributeType. + NUMERICAL (1): + The value of the numerical field will be used to dynamically + update the boost amount. In this case, the attribute_value + (the x value) of the control point will be the actual value + of the numerical field for which the boost_amount is + specified. + FRESHNESS (2): + For the freshness use case the attribute value will be the + duration between the current time and the date in the + datetime field specified. The value must be formatted as an + XSD ``dayTimeDuration`` value (a restricted subset of an ISO + 8601 duration value). The pattern for this is: + ``[nD][T[nH][nM][nS]]``. E.g. ``5D``, ``3DT12H30M``, + ``T24H``. + """ + ATTRIBUTE_TYPE_UNSPECIFIED = 0 + NUMERICAL = 1 + FRESHNESS = 2 + + class InterpolationType(proto.Enum): + r"""The interpolation type to be applied. Default will be linear + (Piecewise Linear). + + Values: + INTERPOLATION_TYPE_UNSPECIFIED (0): + Interpolation type is unspecified. In this + case, it defaults to Linear. + LINEAR (1): + Piecewise linear interpolation will be + applied. + """ + INTERPOLATION_TYPE_UNSPECIFIED = 0 + LINEAR = 1 + + class ControlPoint(proto.Message): + r"""The control points used to define the curve. The curve + defined through these control points can only be monotonically + increasing or decreasing(constant values are acceptable). + + Attributes: + attribute_value (str): + Can be one of: + + 1. The numerical field value. + 2. The duration spec for freshness: The value must be + formatted as an XSD ``dayTimeDuration`` value (a + restricted subset of an ISO 8601 duration value). The + pattern for this is: ``[nD][T[nH][nM][nS]]``. + boost_amount (float): + The value between -1 to 1 by which to boost the score if the + attribute_value evaluates to the value specified above. + """ + + attribute_value: str = proto.Field( + proto.STRING, + number=1, + ) + boost_amount: float = proto.Field( + proto.FLOAT, + number=2, + ) + + field_name: str = proto.Field( + proto.STRING, + number=1, + ) + attribute_type: "SearchRequest.BoostSpec.ConditionBoostSpec.BoostControlSpec.AttributeType" = proto.Field( + proto.ENUM, + number=2, + enum="SearchRequest.BoostSpec.ConditionBoostSpec.BoostControlSpec.AttributeType", + ) + interpolation_type: "SearchRequest.BoostSpec.ConditionBoostSpec.BoostControlSpec.InterpolationType" = proto.Field( + proto.ENUM, + number=3, + enum="SearchRequest.BoostSpec.ConditionBoostSpec.BoostControlSpec.InterpolationType", + ) + control_points: MutableSequence[ + "SearchRequest.BoostSpec.ConditionBoostSpec.BoostControlSpec.ControlPoint" + ] = proto.RepeatedField( + proto.MESSAGE, + number=4, + message="SearchRequest.BoostSpec.ConditionBoostSpec.BoostControlSpec.ControlPoint", + ) + condition: str = proto.Field( proto.STRING, number=1, @@ -534,6 +662,11 @@ class ConditionBoostSpec(proto.Message): proto.FLOAT, number=2, ) + boost_control_spec: "SearchRequest.BoostSpec.ConditionBoostSpec.BoostControlSpec" = proto.Field( + proto.MESSAGE, + number=3, + message="SearchRequest.BoostSpec.ConditionBoostSpec.BoostControlSpec", + ) condition_boost_specs: MutableSequence[ "SearchRequest.BoostSpec.ConditionBoostSpec" @@ -747,6 +880,15 @@ class SummarySpec(proto.Message): model_spec (google.cloud.discoveryengine_v1beta.types.SearchRequest.ContentSearchSpec.SummarySpec.ModelSpec): If specified, the spec will be used to modify the model specification provided to the LLM. + use_semantic_chunks (bool): + If true, answer will be generated from most + relevant chunks from top search results. This + feature will improve summary quality. Note that + with this feature enabled, not all top search + results will be referenced and included in the + reference list, so the citation source index + only points to the search results listed in the + reference list. """ class ModelPromptSpec(proto.Message): @@ -774,11 +916,14 @@ class ModelSpec(proto.Message): Supported values are: - ``stable``: string. Default value when no value is - specified. Uses a generally available, fine-tuned version - of the text-bison@001 model. - - ``preview``: string. (Public preview) Uses a fine-tuned - version of the text-bison@002 model. This model works - only for summaries in English. + specified. Uses a generally available, fine-tuned model. + For more information, see `Answer generation model + versions and + lifecycle `__. + - ``preview``: string. (Public preview) Uses a preview + model. For more information, see `Answer generation model + versions and + lifecycle `__. """ version: str = proto.Field( @@ -818,6 +963,10 @@ class ModelSpec(proto.Message): message="SearchRequest.ContentSearchSpec.SummarySpec.ModelSpec", ) ) + use_semantic_chunks: bool = proto.Field( + proto.BOOL, + number=8, + ) class ExtractiveContentSpec(proto.Message): r"""A specification for configuring the extractive content in a @@ -861,12 +1010,10 @@ class ExtractiveContentSpec(proto.Message): ``max_extractive_segment_count``. return_extractive_segment_score (bool): Specifies whether to return the confidence score from the - extractive segments in each search result. The default value - is ``false``. - - Note: this is a priavte preview feature and only works for - allowlisted users, please reach out to Cloud Support team if - you want to use it. + extractive segments in each search result. This feature is + available only for new or allowlisted data stores. To + allowlist your data store, contact your Customer Engineer. + The default value is ``false``. num_previous_segments (int): Specifies whether to also include the adjacent from each selected segments. Return at most ``num_previous_segments`` @@ -1106,6 +1253,10 @@ class SearchResponse(proto.Message): applied_controls (MutableSequence[str]): Controls applied as part of the Control service. + geo_search_debug_info (MutableSequence[google.cloud.discoveryengine_v1beta.types.SearchResponse.GeoSearchDebugInfo]): + Debug information specifically related to + forward geocoding issues arising from + Geolocation Search. query_expansion_info (google.cloud.discoveryengine_v1beta.types.SearchResponse.QueryExpansionInfo): Query expansion information for the returned results. @@ -1422,8 +1573,30 @@ class Reference(proto.Message): ``projects/*/locations/*/collections/*/dataStores/*/branches/*/documents/*``. uri (str): Cloud Storage or HTTP uri for the document. + chunk_contents (MutableSequence[google.cloud.discoveryengine_v1beta.types.SearchResponse.Summary.Reference.ChunkContent]): + List of cited chunk contents derived from + document content. """ + class ChunkContent(proto.Message): + r"""Chunk content. + + Attributes: + content (str): + Chunk textual content. + page_identifier (str): + Page identifier. + """ + + content: str = proto.Field( + proto.STRING, + number=1, + ) + page_identifier: str = proto.Field( + proto.STRING, + number=2, + ) + title: str = proto.Field( proto.STRING, number=1, @@ -1436,6 +1609,13 @@ class Reference(proto.Message): proto.STRING, number=3, ) + chunk_contents: MutableSequence[ + "SearchResponse.Summary.Reference.ChunkContent" + ] = proto.RepeatedField( + proto.MESSAGE, + number=4, + message="SearchResponse.Summary.Reference.ChunkContent", + ) class SummaryWithMetadata(proto.Message): r"""Summary with metadata information. @@ -1490,6 +1670,27 @@ class SummaryWithMetadata(proto.Message): ) ) + class GeoSearchDebugInfo(proto.Message): + r"""Debug information specifically related to forward geocoding + issues arising from Geolocation Search. + + Attributes: + original_address_query (str): + The address from which forward geocoding + ingestion produced issues. + error_message (str): + The error produced. + """ + + original_address_query: str = proto.Field( + proto.STRING, + number=1, + ) + error_message: str = proto.Field( + proto.STRING, + number=2, + ) + class QueryExpansionInfo(proto.Message): r"""Information describing query expansion including whether expansion has occurred. @@ -1562,6 +1763,11 @@ def raw_page(self): proto.STRING, number=10, ) + geo_search_debug_info: MutableSequence[GeoSearchDebugInfo] = proto.RepeatedField( + proto.MESSAGE, + number=16, + message=GeoSearchDebugInfo, + ) query_expansion_info: QueryExpansionInfo = proto.Field( proto.MESSAGE, number=14, diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/search_tuning_service.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/search_tuning_service.py index 14eb50087f27..ca89e976a977 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/search_tuning_service.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/search_tuning_service.py @@ -158,8 +158,14 @@ class TrainCustomModelResponse(proto.Message): - **bad-data**: The training data quality is bad. - **no-improvement**: Tuning didn't improve performance. Won't deploy. - - **in-progress**: Model training is in progress. + - **in-progress**: Model training job creation is in + progress. + - **training**: Model is actively training. + - **evaluating**: The model is evaluating trained metrics. + - **indexing**: The model trained metrics are indexing. - **ready**: The model is ready for serving. + metrics (MutableMapping[str, float]): + The metrics of the trained model. """ error_samples: MutableSequence[status_pb2.Status] = proto.RepeatedField( @@ -176,6 +182,11 @@ class TrainCustomModelResponse(proto.Message): proto.STRING, number=3, ) + metrics: MutableMapping[str, float] = proto.MapField( + proto.STRING, + proto.DOUBLE, + number=4, + ) class TrainCustomModelMetadata(proto.Message): diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/session.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/session.py new file mode 100644 index 000000000000..527789c3d771 --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/session.py @@ -0,0 +1,140 @@ +# -*- 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 timestamp_pb2 # type: ignore +import proto # type: ignore + +__protobuf__ = proto.module( + package="google.cloud.discoveryengine.v1beta", + manifest={ + "Session", + "Query", + }, +) + + +class Session(proto.Message): + r"""External session proto definition. + + Attributes: + name (str): + Immutable. Fully qualified name + ``project/*/locations/global/collections/{collection}/engines/{engine}/sessions/*`` + state (google.cloud.discoveryengine_v1beta.types.Session.State): + The state of the session. + user_pseudo_id (str): + A unique identifier for tracking users. + turns (MutableSequence[google.cloud.discoveryengine_v1beta.types.Session.Turn]): + Turns. + start_time (google.protobuf.timestamp_pb2.Timestamp): + Output only. The time the session started. + end_time (google.protobuf.timestamp_pb2.Timestamp): + Output only. The time the session finished. + """ + + class State(proto.Enum): + r"""Enumeration of the state of the session. + + Values: + STATE_UNSPECIFIED (0): + State is unspecified. + IN_PROGRESS (1): + The session is currently open. + """ + STATE_UNSPECIFIED = 0 + IN_PROGRESS = 1 + + class Turn(proto.Message): + r"""Represents a turn, including a query from the user and a + answer from service. + + Attributes: + query (google.cloud.discoveryengine_v1beta.types.Query): + The user query. + answer (str): + The resource name of the answer to the user + query. + """ + + query: "Query" = proto.Field( + proto.MESSAGE, + number=1, + message="Query", + ) + answer: str = proto.Field( + proto.STRING, + number=2, + ) + + name: str = proto.Field( + proto.STRING, + number=1, + ) + state: State = proto.Field( + proto.ENUM, + number=2, + enum=State, + ) + user_pseudo_id: str = proto.Field( + proto.STRING, + number=3, + ) + turns: MutableSequence[Turn] = proto.RepeatedField( + proto.MESSAGE, + number=4, + message=Turn, + ) + start_time: timestamp_pb2.Timestamp = proto.Field( + proto.MESSAGE, + number=5, + message=timestamp_pb2.Timestamp, + ) + end_time: timestamp_pb2.Timestamp = proto.Field( + proto.MESSAGE, + number=6, + message=timestamp_pb2.Timestamp, + ) + + +class Query(proto.Message): + r"""Defines a user inputed query. + + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + + Attributes: + text (str): + Plain text. + + This field is a member of `oneof`_ ``content``. + query_id (str): + Unique Id for the query. + """ + + text: str = proto.Field( + proto.STRING, + number=2, + oneof="content", + ) + query_id: str = proto.Field( + proto.STRING, + number=1, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/user_event.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/user_event.py index 73f70c956a23..dc6c1ee72dce 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/user_event.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/user_event.py @@ -363,7 +363,7 @@ class PageInfo(proto.Message): To represent full path of category, use '>' sign to separate different hierarchies. If '>' is part of the category name, - please replace it with other character(s). + replace it with other character(s). Category pages include special pages such as sales or promotions. For instance, a special sale page may have the diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1_generated_engine_service_create_engine_async.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1_generated_engine_service_create_engine_async.py index 61dc6bd243d1..73c826285538 100644 --- a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1_generated_engine_service_create_engine_async.py +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1_generated_engine_service_create_engine_async.py @@ -41,7 +41,7 @@ async def sample_create_engine(): # Initialize request argument(s) engine = discoveryengine_v1.Engine() engine.display_name = "display_name_value" - engine.solution_type = "SOLUTION_TYPE_CHAT" + engine.solution_type = "SOLUTION_TYPE_GENERATIVE_CHAT" request = discoveryengine_v1.CreateEngineRequest( parent="parent_value", diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1_generated_engine_service_create_engine_sync.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1_generated_engine_service_create_engine_sync.py index ff7506b184aa..ab92d5b30f4a 100644 --- a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1_generated_engine_service_create_engine_sync.py +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1_generated_engine_service_create_engine_sync.py @@ -41,7 +41,7 @@ def sample_create_engine(): # Initialize request argument(s) engine = discoveryengine_v1.Engine() engine.display_name = "display_name_value" - engine.solution_type = "SOLUTION_TYPE_CHAT" + engine.solution_type = "SOLUTION_TYPE_GENERATIVE_CHAT" request = discoveryengine_v1.CreateEngineRequest( parent="parent_value", diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1_generated_engine_service_update_engine_async.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1_generated_engine_service_update_engine_async.py index 06712cd09e24..69e2994e1ff8 100644 --- a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1_generated_engine_service_update_engine_async.py +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1_generated_engine_service_update_engine_async.py @@ -41,7 +41,7 @@ async def sample_update_engine(): # Initialize request argument(s) engine = discoveryengine_v1.Engine() engine.display_name = "display_name_value" - engine.solution_type = "SOLUTION_TYPE_CHAT" + engine.solution_type = "SOLUTION_TYPE_GENERATIVE_CHAT" request = discoveryengine_v1.UpdateEngineRequest( engine=engine, diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1_generated_engine_service_update_engine_sync.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1_generated_engine_service_update_engine_sync.py index 7a2ae0776cf0..2781b7c8b7df 100644 --- a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1_generated_engine_service_update_engine_sync.py +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1_generated_engine_service_update_engine_sync.py @@ -41,7 +41,7 @@ def sample_update_engine(): # Initialize request argument(s) engine = discoveryengine_v1.Engine() engine.display_name = "display_name_value" - engine.solution_type = "SOLUTION_TYPE_CHAT" + engine.solution_type = "SOLUTION_TYPE_GENERATIVE_CHAT" request = discoveryengine_v1.UpdateEngineRequest( engine=engine, diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1_generated_recommendation_service_recommend_async.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1_generated_recommendation_service_recommend_async.py new file mode 100644 index 000000000000..37f88a83e9e1 --- /dev/null +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1_generated_recommendation_service_recommend_async.py @@ -0,0 +1,57 @@ +# -*- 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 Recommend +# 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-discoveryengine + + +# [START discoveryengine_v1_generated_RecommendationService_Recommend_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 discoveryengine_v1 + + +async def sample_recommend(): + # Create a client + client = discoveryengine_v1.RecommendationServiceAsyncClient() + + # Initialize request argument(s) + user_event = discoveryengine_v1.UserEvent() + user_event.event_type = "event_type_value" + user_event.user_pseudo_id = "user_pseudo_id_value" + + request = discoveryengine_v1.RecommendRequest( + serving_config="serving_config_value", + user_event=user_event, + ) + + # Make the request + response = await client.recommend(request=request) + + # Handle the response + print(response) + +# [END discoveryengine_v1_generated_RecommendationService_Recommend_async] diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1_generated_recommendation_service_recommend_sync.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1_generated_recommendation_service_recommend_sync.py new file mode 100644 index 000000000000..968d52bf1ad7 --- /dev/null +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1_generated_recommendation_service_recommend_sync.py @@ -0,0 +1,57 @@ +# -*- 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 Recommend +# 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-discoveryengine + + +# [START discoveryengine_v1_generated_RecommendationService_Recommend_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 discoveryengine_v1 + + +def sample_recommend(): + # Create a client + client = discoveryengine_v1.RecommendationServiceClient() + + # Initialize request argument(s) + user_event = discoveryengine_v1.UserEvent() + user_event.event_type = "event_type_value" + user_event.user_pseudo_id = "user_pseudo_id_value" + + request = discoveryengine_v1.RecommendRequest( + serving_config="serving_config_value", + user_event=user_event, + ) + + # Make the request + response = client.recommend(request=request) + + # Handle the response + print(response) + +# [END discoveryengine_v1_generated_RecommendationService_Recommend_sync] diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_conversational_search_service_answer_query_async.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_conversational_search_service_answer_query_async.py new file mode 100644 index 000000000000..fb9fe8c870a9 --- /dev/null +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_conversational_search_service_answer_query_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 AnswerQuery +# 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-discoveryengine + + +# [START discoveryengine_v1alpha_generated_ConversationalSearchService_AnswerQuery_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 discoveryengine_v1alpha + + +async def sample_answer_query(): + # Create a client + client = discoveryengine_v1alpha.ConversationalSearchServiceAsyncClient() + + # Initialize request argument(s) + query = discoveryengine_v1alpha.Query() + query.text = "text_value" + + request = discoveryengine_v1alpha.AnswerQueryRequest( + serving_config="serving_config_value", + query=query, + ) + + # Make the request + response = await client.answer_query(request=request) + + # Handle the response + print(response) + +# [END discoveryengine_v1alpha_generated_ConversationalSearchService_AnswerQuery_async] diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_conversational_search_service_answer_query_sync.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_conversational_search_service_answer_query_sync.py new file mode 100644 index 000000000000..a790fa21f698 --- /dev/null +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_conversational_search_service_answer_query_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 AnswerQuery +# 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-discoveryengine + + +# [START discoveryengine_v1alpha_generated_ConversationalSearchService_AnswerQuery_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 discoveryengine_v1alpha + + +def sample_answer_query(): + # Create a client + client = discoveryengine_v1alpha.ConversationalSearchServiceClient() + + # Initialize request argument(s) + query = discoveryengine_v1alpha.Query() + query.text = "text_value" + + request = discoveryengine_v1alpha.AnswerQueryRequest( + serving_config="serving_config_value", + query=query, + ) + + # Make the request + response = client.answer_query(request=request) + + # Handle the response + print(response) + +# [END discoveryengine_v1alpha_generated_ConversationalSearchService_AnswerQuery_sync] diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_conversational_search_service_create_session_async.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_conversational_search_service_create_session_async.py new file mode 100644 index 000000000000..57ccae1e2ba4 --- /dev/null +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_conversational_search_service_create_session_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 CreateSession +# 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-discoveryengine + + +# [START discoveryengine_v1alpha_generated_ConversationalSearchService_CreateSession_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 discoveryengine_v1alpha + + +async def sample_create_session(): + # Create a client + client = discoveryengine_v1alpha.ConversationalSearchServiceAsyncClient() + + # Initialize request argument(s) + request = discoveryengine_v1alpha.CreateSessionRequest( + parent="parent_value", + ) + + # Make the request + response = await client.create_session(request=request) + + # Handle the response + print(response) + +# [END discoveryengine_v1alpha_generated_ConversationalSearchService_CreateSession_async] diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_conversational_search_service_create_session_sync.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_conversational_search_service_create_session_sync.py new file mode 100644 index 000000000000..d98cd44d6f12 --- /dev/null +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_conversational_search_service_create_session_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 CreateSession +# 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-discoveryengine + + +# [START discoveryengine_v1alpha_generated_ConversationalSearchService_CreateSession_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 discoveryengine_v1alpha + + +def sample_create_session(): + # Create a client + client = discoveryengine_v1alpha.ConversationalSearchServiceClient() + + # Initialize request argument(s) + request = discoveryengine_v1alpha.CreateSessionRequest( + parent="parent_value", + ) + + # Make the request + response = client.create_session(request=request) + + # Handle the response + print(response) + +# [END discoveryengine_v1alpha_generated_ConversationalSearchService_CreateSession_sync] diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_conversational_search_service_delete_session_async.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_conversational_search_service_delete_session_async.py new file mode 100644 index 000000000000..7cee4dd510bc --- /dev/null +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_conversational_search_service_delete_session_async.py @@ -0,0 +1,50 @@ +# -*- 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 DeleteSession +# 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-discoveryengine + + +# [START discoveryengine_v1alpha_generated_ConversationalSearchService_DeleteSession_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 discoveryengine_v1alpha + + +async def sample_delete_session(): + # Create a client + client = discoveryengine_v1alpha.ConversationalSearchServiceAsyncClient() + + # Initialize request argument(s) + request = discoveryengine_v1alpha.DeleteSessionRequest( + name="name_value", + ) + + # Make the request + await client.delete_session(request=request) + + +# [END discoveryengine_v1alpha_generated_ConversationalSearchService_DeleteSession_async] diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_conversational_search_service_delete_session_sync.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_conversational_search_service_delete_session_sync.py new file mode 100644 index 000000000000..d5ec084b7199 --- /dev/null +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_conversational_search_service_delete_session_sync.py @@ -0,0 +1,50 @@ +# -*- 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 DeleteSession +# 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-discoveryengine + + +# [START discoveryengine_v1alpha_generated_ConversationalSearchService_DeleteSession_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 discoveryengine_v1alpha + + +def sample_delete_session(): + # Create a client + client = discoveryengine_v1alpha.ConversationalSearchServiceClient() + + # Initialize request argument(s) + request = discoveryengine_v1alpha.DeleteSessionRequest( + name="name_value", + ) + + # Make the request + client.delete_session(request=request) + + +# [END discoveryengine_v1alpha_generated_ConversationalSearchService_DeleteSession_sync] diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_conversational_search_service_get_answer_async.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_conversational_search_service_get_answer_async.py new file mode 100644 index 000000000000..abcfc971108f --- /dev/null +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_conversational_search_service_get_answer_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 GetAnswer +# 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-discoveryengine + + +# [START discoveryengine_v1alpha_generated_ConversationalSearchService_GetAnswer_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 discoveryengine_v1alpha + + +async def sample_get_answer(): + # Create a client + client = discoveryengine_v1alpha.ConversationalSearchServiceAsyncClient() + + # Initialize request argument(s) + request = discoveryengine_v1alpha.GetAnswerRequest( + name="name_value", + ) + + # Make the request + response = await client.get_answer(request=request) + + # Handle the response + print(response) + +# [END discoveryengine_v1alpha_generated_ConversationalSearchService_GetAnswer_async] diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_conversational_search_service_get_answer_sync.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_conversational_search_service_get_answer_sync.py new file mode 100644 index 000000000000..731e74093c23 --- /dev/null +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_conversational_search_service_get_answer_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 GetAnswer +# 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-discoveryengine + + +# [START discoveryengine_v1alpha_generated_ConversationalSearchService_GetAnswer_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 discoveryengine_v1alpha + + +def sample_get_answer(): + # Create a client + client = discoveryengine_v1alpha.ConversationalSearchServiceClient() + + # Initialize request argument(s) + request = discoveryengine_v1alpha.GetAnswerRequest( + name="name_value", + ) + + # Make the request + response = client.get_answer(request=request) + + # Handle the response + print(response) + +# [END discoveryengine_v1alpha_generated_ConversationalSearchService_GetAnswer_sync] diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_conversational_search_service_get_session_async.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_conversational_search_service_get_session_async.py new file mode 100644 index 000000000000..643a2419978b --- /dev/null +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_conversational_search_service_get_session_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 GetSession +# 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-discoveryengine + + +# [START discoveryengine_v1alpha_generated_ConversationalSearchService_GetSession_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 discoveryengine_v1alpha + + +async def sample_get_session(): + # Create a client + client = discoveryengine_v1alpha.ConversationalSearchServiceAsyncClient() + + # Initialize request argument(s) + request = discoveryengine_v1alpha.GetSessionRequest( + name="name_value", + ) + + # Make the request + response = await client.get_session(request=request) + + # Handle the response + print(response) + +# [END discoveryengine_v1alpha_generated_ConversationalSearchService_GetSession_async] diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_conversational_search_service_get_session_sync.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_conversational_search_service_get_session_sync.py new file mode 100644 index 000000000000..e8a0f41da76b --- /dev/null +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_conversational_search_service_get_session_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 GetSession +# 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-discoveryengine + + +# [START discoveryengine_v1alpha_generated_ConversationalSearchService_GetSession_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 discoveryengine_v1alpha + + +def sample_get_session(): + # Create a client + client = discoveryengine_v1alpha.ConversationalSearchServiceClient() + + # Initialize request argument(s) + request = discoveryengine_v1alpha.GetSessionRequest( + name="name_value", + ) + + # Make the request + response = client.get_session(request=request) + + # Handle the response + print(response) + +# [END discoveryengine_v1alpha_generated_ConversationalSearchService_GetSession_sync] diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_conversational_search_service_list_sessions_async.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_conversational_search_service_list_sessions_async.py new file mode 100644 index 000000000000..fdcceaca10cf --- /dev/null +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_conversational_search_service_list_sessions_async.py @@ -0,0 +1,53 @@ +# -*- 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 ListSessions +# 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-discoveryengine + + +# [START discoveryengine_v1alpha_generated_ConversationalSearchService_ListSessions_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 discoveryengine_v1alpha + + +async def sample_list_sessions(): + # Create a client + client = discoveryengine_v1alpha.ConversationalSearchServiceAsyncClient() + + # Initialize request argument(s) + request = discoveryengine_v1alpha.ListSessionsRequest( + parent="parent_value", + ) + + # Make the request + page_result = client.list_sessions(request=request) + + # Handle the response + async for response in page_result: + print(response) + +# [END discoveryengine_v1alpha_generated_ConversationalSearchService_ListSessions_async] diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_conversational_search_service_list_sessions_sync.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_conversational_search_service_list_sessions_sync.py new file mode 100644 index 000000000000..18a1bf35e778 --- /dev/null +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_conversational_search_service_list_sessions_sync.py @@ -0,0 +1,53 @@ +# -*- 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 ListSessions +# 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-discoveryengine + + +# [START discoveryengine_v1alpha_generated_ConversationalSearchService_ListSessions_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 discoveryengine_v1alpha + + +def sample_list_sessions(): + # Create a client + client = discoveryengine_v1alpha.ConversationalSearchServiceClient() + + # Initialize request argument(s) + request = discoveryengine_v1alpha.ListSessionsRequest( + parent="parent_value", + ) + + # Make the request + page_result = client.list_sessions(request=request) + + # Handle the response + for response in page_result: + print(response) + +# [END discoveryengine_v1alpha_generated_ConversationalSearchService_ListSessions_sync] diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_conversational_search_service_update_session_async.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_conversational_search_service_update_session_async.py new file mode 100644 index 000000000000..cc675a59837e --- /dev/null +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_conversational_search_service_update_session_async.py @@ -0,0 +1,51 @@ +# -*- 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 UpdateSession +# 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-discoveryengine + + +# [START discoveryengine_v1alpha_generated_ConversationalSearchService_UpdateSession_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 discoveryengine_v1alpha + + +async def sample_update_session(): + # Create a client + client = discoveryengine_v1alpha.ConversationalSearchServiceAsyncClient() + + # Initialize request argument(s) + request = discoveryengine_v1alpha.UpdateSessionRequest( + ) + + # Make the request + response = await client.update_session(request=request) + + # Handle the response + print(response) + +# [END discoveryengine_v1alpha_generated_ConversationalSearchService_UpdateSession_async] diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_conversational_search_service_update_session_sync.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_conversational_search_service_update_session_sync.py new file mode 100644 index 000000000000..585e0688b22b --- /dev/null +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_conversational_search_service_update_session_sync.py @@ -0,0 +1,51 @@ +# -*- 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 UpdateSession +# 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-discoveryengine + + +# [START discoveryengine_v1alpha_generated_ConversationalSearchService_UpdateSession_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 discoveryengine_v1alpha + + +def sample_update_session(): + # Create a client + client = discoveryengine_v1alpha.ConversationalSearchServiceClient() + + # Initialize request argument(s) + request = discoveryengine_v1alpha.UpdateSessionRequest( + ) + + # Make the request + response = client.update_session(request=request) + + # Handle the response + print(response) + +# [END discoveryengine_v1alpha_generated_ConversationalSearchService_UpdateSession_sync] diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_document_service_get_processed_document_async.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_document_service_get_processed_document_async.py new file mode 100644 index 000000000000..0258cb3c2030 --- /dev/null +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_document_service_get_processed_document_async.py @@ -0,0 +1,53 @@ +# -*- 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 GetProcessedDocument +# 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-discoveryengine + + +# [START discoveryengine_v1alpha_generated_DocumentService_GetProcessedDocument_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 discoveryengine_v1alpha + + +async def sample_get_processed_document(): + # Create a client + client = discoveryengine_v1alpha.DocumentServiceAsyncClient() + + # Initialize request argument(s) + request = discoveryengine_v1alpha.GetProcessedDocumentRequest( + name="name_value", + processed_document_type="CHUNKED_DOCUMENT", + ) + + # Make the request + response = await client.get_processed_document(request=request) + + # Handle the response + print(response) + +# [END discoveryengine_v1alpha_generated_DocumentService_GetProcessedDocument_async] diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_document_service_get_processed_document_sync.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_document_service_get_processed_document_sync.py new file mode 100644 index 000000000000..7581ccb4e33d --- /dev/null +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_document_service_get_processed_document_sync.py @@ -0,0 +1,53 @@ +# -*- 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 GetProcessedDocument +# 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-discoveryengine + + +# [START discoveryengine_v1alpha_generated_DocumentService_GetProcessedDocument_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 discoveryengine_v1alpha + + +def sample_get_processed_document(): + # Create a client + client = discoveryengine_v1alpha.DocumentServiceClient() + + # Initialize request argument(s) + request = discoveryengine_v1alpha.GetProcessedDocumentRequest( + name="name_value", + processed_document_type="CHUNKED_DOCUMENT", + ) + + # Make the request + response = client.get_processed_document(request=request) + + # Handle the response + print(response) + +# [END discoveryengine_v1alpha_generated_DocumentService_GetProcessedDocument_sync] diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_engine_service_create_engine_async.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_engine_service_create_engine_async.py index 6f9f40a45c69..5a694ea7edb7 100644 --- a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_engine_service_create_engine_async.py +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_engine_service_create_engine_async.py @@ -41,7 +41,7 @@ async def sample_create_engine(): # Initialize request argument(s) engine = discoveryengine_v1alpha.Engine() engine.display_name = "display_name_value" - engine.solution_type = "SOLUTION_TYPE_CHAT" + engine.solution_type = "SOLUTION_TYPE_GENERATIVE_CHAT" request = discoveryengine_v1alpha.CreateEngineRequest( parent="parent_value", diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_engine_service_create_engine_sync.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_engine_service_create_engine_sync.py index 91cdd1082d64..7e0e69e63750 100644 --- a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_engine_service_create_engine_sync.py +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_engine_service_create_engine_sync.py @@ -41,7 +41,7 @@ def sample_create_engine(): # Initialize request argument(s) engine = discoveryengine_v1alpha.Engine() engine.display_name = "display_name_value" - engine.solution_type = "SOLUTION_TYPE_CHAT" + engine.solution_type = "SOLUTION_TYPE_GENERATIVE_CHAT" request = discoveryengine_v1alpha.CreateEngineRequest( parent="parent_value", diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_engine_service_update_engine_async.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_engine_service_update_engine_async.py index 36c28cbbc63f..c87725dfe050 100644 --- a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_engine_service_update_engine_async.py +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_engine_service_update_engine_async.py @@ -41,7 +41,7 @@ async def sample_update_engine(): # Initialize request argument(s) engine = discoveryengine_v1alpha.Engine() engine.display_name = "display_name_value" - engine.solution_type = "SOLUTION_TYPE_CHAT" + engine.solution_type = "SOLUTION_TYPE_GENERATIVE_CHAT" request = discoveryengine_v1alpha.UpdateEngineRequest( engine=engine, diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_engine_service_update_engine_sync.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_engine_service_update_engine_sync.py index 54038b9efbac..68ea0949794f 100644 --- a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_engine_service_update_engine_sync.py +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_engine_service_update_engine_sync.py @@ -41,7 +41,7 @@ def sample_update_engine(): # Initialize request argument(s) engine = discoveryengine_v1alpha.Engine() engine.display_name = "display_name_value" - engine.solution_type = "SOLUTION_TYPE_CHAT" + engine.solution_type = "SOLUTION_TYPE_GENERATIVE_CHAT" request = discoveryengine_v1alpha.UpdateEngineRequest( engine=engine, diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_grounded_generation_service_check_grounding_async.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_grounded_generation_service_check_grounding_async.py new file mode 100644 index 000000000000..824208e482b9 --- /dev/null +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_grounded_generation_service_check_grounding_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 CheckGrounding +# 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-discoveryengine + + +# [START discoveryengine_v1alpha_generated_GroundedGenerationService_CheckGrounding_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 discoveryengine_v1alpha + + +async def sample_check_grounding(): + # Create a client + client = discoveryengine_v1alpha.GroundedGenerationServiceAsyncClient() + + # Initialize request argument(s) + request = discoveryengine_v1alpha.CheckGroundingRequest( + grounding_config="grounding_config_value", + ) + + # Make the request + response = await client.check_grounding(request=request) + + # Handle the response + print(response) + +# [END discoveryengine_v1alpha_generated_GroundedGenerationService_CheckGrounding_async] diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_grounded_generation_service_check_grounding_sync.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_grounded_generation_service_check_grounding_sync.py new file mode 100644 index 000000000000..e3e4c5b73992 --- /dev/null +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_grounded_generation_service_check_grounding_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 CheckGrounding +# 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-discoveryengine + + +# [START discoveryengine_v1alpha_generated_GroundedGenerationService_CheckGrounding_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 discoveryengine_v1alpha + + +def sample_check_grounding(): + # Create a client + client = discoveryengine_v1alpha.GroundedGenerationServiceClient() + + # Initialize request argument(s) + request = discoveryengine_v1alpha.CheckGroundingRequest( + grounding_config="grounding_config_value", + ) + + # Make the request + response = client.check_grounding(request=request) + + # Handle the response + print(response) + +# [END discoveryengine_v1alpha_generated_GroundedGenerationService_CheckGrounding_sync] diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_project_service_get_project_async.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_project_service_get_project_async.py new file mode 100644 index 000000000000..6519232635c8 --- /dev/null +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_project_service_get_project_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 GetProject +# 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-discoveryengine + + +# [START discoveryengine_v1alpha_generated_ProjectService_GetProject_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 discoveryengine_v1alpha + + +async def sample_get_project(): + # Create a client + client = discoveryengine_v1alpha.ProjectServiceAsyncClient() + + # Initialize request argument(s) + request = discoveryengine_v1alpha.GetProjectRequest( + name="name_value", + ) + + # Make the request + response = await client.get_project(request=request) + + # Handle the response + print(response) + +# [END discoveryengine_v1alpha_generated_ProjectService_GetProject_async] diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_project_service_get_project_sync.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_project_service_get_project_sync.py new file mode 100644 index 000000000000..d9188687070c --- /dev/null +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_project_service_get_project_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 GetProject +# 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-discoveryengine + + +# [START discoveryengine_v1alpha_generated_ProjectService_GetProject_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 discoveryengine_v1alpha + + +def sample_get_project(): + # Create a client + client = discoveryengine_v1alpha.ProjectServiceClient() + + # Initialize request argument(s) + request = discoveryengine_v1alpha.GetProjectRequest( + name="name_value", + ) + + # Make the request + response = client.get_project(request=request) + + # Handle the response + print(response) + +# [END discoveryengine_v1alpha_generated_ProjectService_GetProject_sync] diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_project_service_provision_project_async.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_project_service_provision_project_async.py new file mode 100644 index 000000000000..f86503811bf7 --- /dev/null +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_project_service_provision_project_async.py @@ -0,0 +1,58 @@ +# -*- 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 ProvisionProject +# 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-discoveryengine + + +# [START discoveryengine_v1alpha_generated_ProjectService_ProvisionProject_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 discoveryengine_v1alpha + + +async def sample_provision_project(): + # Create a client + client = discoveryengine_v1alpha.ProjectServiceAsyncClient() + + # Initialize request argument(s) + request = discoveryengine_v1alpha.ProvisionProjectRequest( + name="name_value", + accept_data_use_terms=True, + data_use_terms_version="data_use_terms_version_value", + ) + + # Make the request + operation = client.provision_project(request=request) + + print("Waiting for operation to complete...") + + response = (await operation).result() + + # Handle the response + print(response) + +# [END discoveryengine_v1alpha_generated_ProjectService_ProvisionProject_async] diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_project_service_provision_project_sync.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_project_service_provision_project_sync.py new file mode 100644 index 000000000000..2b3206200821 --- /dev/null +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_project_service_provision_project_sync.py @@ -0,0 +1,58 @@ +# -*- 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 ProvisionProject +# 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-discoveryengine + + +# [START discoveryengine_v1alpha_generated_ProjectService_ProvisionProject_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 discoveryengine_v1alpha + + +def sample_provision_project(): + # Create a client + client = discoveryengine_v1alpha.ProjectServiceClient() + + # Initialize request argument(s) + request = discoveryengine_v1alpha.ProvisionProjectRequest( + name="name_value", + accept_data_use_terms=True, + data_use_terms_version="data_use_terms_version_value", + ) + + # Make the request + operation = client.provision_project(request=request) + + print("Waiting for operation to complete...") + + response = operation.result() + + # Handle the response + print(response) + +# [END discoveryengine_v1alpha_generated_ProjectService_ProvisionProject_sync] diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_project_service_report_consent_change_async.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_project_service_report_consent_change_async.py new file mode 100644 index 000000000000..a015be9ab0ac --- /dev/null +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_project_service_report_consent_change_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 ReportConsentChange +# 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-discoveryengine + + +# [START discoveryengine_v1alpha_generated_ProjectService_ReportConsentChange_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 discoveryengine_v1alpha + + +async def sample_report_consent_change(): + # Create a client + client = discoveryengine_v1alpha.ProjectServiceAsyncClient() + + # Initialize request argument(s) + request = discoveryengine_v1alpha.ReportConsentChangeRequest( + consent_change_action="ACCEPT", + project="project_value", + service_term_id="service_term_id_value", + service_term_version="service_term_version_value", + ) + + # Make the request + response = await client.report_consent_change(request=request) + + # Handle the response + print(response) + +# [END discoveryengine_v1alpha_generated_ProjectService_ReportConsentChange_async] diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_project_service_report_consent_change_sync.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_project_service_report_consent_change_sync.py new file mode 100644 index 000000000000..962accf31b68 --- /dev/null +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_project_service_report_consent_change_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 ReportConsentChange +# 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-discoveryengine + + +# [START discoveryengine_v1alpha_generated_ProjectService_ReportConsentChange_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 discoveryengine_v1alpha + + +def sample_report_consent_change(): + # Create a client + client = discoveryengine_v1alpha.ProjectServiceClient() + + # Initialize request argument(s) + request = discoveryengine_v1alpha.ReportConsentChangeRequest( + consent_change_action="ACCEPT", + project="project_value", + service_term_id="service_term_id_value", + service_term_version="service_term_version_value", + ) + + # Make the request + response = client.report_consent_change(request=request) + + # Handle the response + print(response) + +# [END discoveryengine_v1alpha_generated_ProjectService_ReportConsentChange_sync] diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_rank_service_rank_async.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_rank_service_rank_async.py new file mode 100644 index 000000000000..e6b87332a454 --- /dev/null +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_rank_service_rank_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 Rank +# 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-discoveryengine + + +# [START discoveryengine_v1alpha_generated_RankService_Rank_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 discoveryengine_v1alpha + + +async def sample_rank(): + # Create a client + client = discoveryengine_v1alpha.RankServiceAsyncClient() + + # Initialize request argument(s) + request = discoveryengine_v1alpha.RankRequest( + ranking_config="ranking_config_value", + ) + + # Make the request + response = await client.rank(request=request) + + # Handle the response + print(response) + +# [END discoveryengine_v1alpha_generated_RankService_Rank_async] diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_rank_service_rank_sync.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_rank_service_rank_sync.py new file mode 100644 index 000000000000..6de6d7dcfd13 --- /dev/null +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_rank_service_rank_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 Rank +# 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-discoveryengine + + +# [START discoveryengine_v1alpha_generated_RankService_Rank_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 discoveryengine_v1alpha + + +def sample_rank(): + # Create a client + client = discoveryengine_v1alpha.RankServiceClient() + + # Initialize request argument(s) + request = discoveryengine_v1alpha.RankRequest( + ranking_config="ranking_config_value", + ) + + # Make the request + response = client.rank(request=request) + + # Handle the response + print(response) + +# [END discoveryengine_v1alpha_generated_RankService_Rank_sync] diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_serving_config_service_update_serving_config_async.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_serving_config_service_update_serving_config_async.py index 091e1cdd0b2e..051ac7c4bce3 100644 --- a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_serving_config_service_update_serving_config_async.py +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_serving_config_service_update_serving_config_async.py @@ -42,7 +42,7 @@ async def sample_update_serving_config(): serving_config = discoveryengine_v1alpha.ServingConfig() serving_config.media_config.content_watched_percentage_threshold = 0.3811 serving_config.display_name = "display_name_value" - serving_config.solution_type = "SOLUTION_TYPE_CHAT" + serving_config.solution_type = "SOLUTION_TYPE_GENERATIVE_CHAT" request = discoveryengine_v1alpha.UpdateServingConfigRequest( serving_config=serving_config, diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_serving_config_service_update_serving_config_sync.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_serving_config_service_update_serving_config_sync.py index 033587269636..993f234ce4f3 100644 --- a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_serving_config_service_update_serving_config_sync.py +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1alpha_generated_serving_config_service_update_serving_config_sync.py @@ -42,7 +42,7 @@ def sample_update_serving_config(): serving_config = discoveryengine_v1alpha.ServingConfig() serving_config.media_config.content_watched_percentage_threshold = 0.3811 serving_config.display_name = "display_name_value" - serving_config.solution_type = "SOLUTION_TYPE_CHAT" + serving_config.solution_type = "SOLUTION_TYPE_GENERATIVE_CHAT" request = discoveryengine_v1alpha.UpdateServingConfigRequest( serving_config=serving_config, diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_conversational_search_service_answer_query_async.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_conversational_search_service_answer_query_async.py new file mode 100644 index 000000000000..c438ce065784 --- /dev/null +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_conversational_search_service_answer_query_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 AnswerQuery +# 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-discoveryengine + + +# [START discoveryengine_v1beta_generated_ConversationalSearchService_AnswerQuery_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 discoveryengine_v1beta + + +async def sample_answer_query(): + # Create a client + client = discoveryengine_v1beta.ConversationalSearchServiceAsyncClient() + + # Initialize request argument(s) + query = discoveryengine_v1beta.Query() + query.text = "text_value" + + request = discoveryengine_v1beta.AnswerQueryRequest( + serving_config="serving_config_value", + query=query, + ) + + # Make the request + response = await client.answer_query(request=request) + + # Handle the response + print(response) + +# [END discoveryengine_v1beta_generated_ConversationalSearchService_AnswerQuery_async] diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_conversational_search_service_answer_query_sync.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_conversational_search_service_answer_query_sync.py new file mode 100644 index 000000000000..759f3e22e787 --- /dev/null +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_conversational_search_service_answer_query_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 AnswerQuery +# 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-discoveryengine + + +# [START discoveryengine_v1beta_generated_ConversationalSearchService_AnswerQuery_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 discoveryengine_v1beta + + +def sample_answer_query(): + # Create a client + client = discoveryengine_v1beta.ConversationalSearchServiceClient() + + # Initialize request argument(s) + query = discoveryengine_v1beta.Query() + query.text = "text_value" + + request = discoveryengine_v1beta.AnswerQueryRequest( + serving_config="serving_config_value", + query=query, + ) + + # Make the request + response = client.answer_query(request=request) + + # Handle the response + print(response) + +# [END discoveryengine_v1beta_generated_ConversationalSearchService_AnswerQuery_sync] diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_conversational_search_service_create_session_async.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_conversational_search_service_create_session_async.py new file mode 100644 index 000000000000..ff50a1043c50 --- /dev/null +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_conversational_search_service_create_session_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 CreateSession +# 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-discoveryengine + + +# [START discoveryengine_v1beta_generated_ConversationalSearchService_CreateSession_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 discoveryengine_v1beta + + +async def sample_create_session(): + # Create a client + client = discoveryengine_v1beta.ConversationalSearchServiceAsyncClient() + + # Initialize request argument(s) + request = discoveryengine_v1beta.CreateSessionRequest( + parent="parent_value", + ) + + # Make the request + response = await client.create_session(request=request) + + # Handle the response + print(response) + +# [END discoveryengine_v1beta_generated_ConversationalSearchService_CreateSession_async] diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_conversational_search_service_create_session_sync.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_conversational_search_service_create_session_sync.py new file mode 100644 index 000000000000..51ba18b0aada --- /dev/null +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_conversational_search_service_create_session_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 CreateSession +# 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-discoveryengine + + +# [START discoveryengine_v1beta_generated_ConversationalSearchService_CreateSession_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 discoveryengine_v1beta + + +def sample_create_session(): + # Create a client + client = discoveryengine_v1beta.ConversationalSearchServiceClient() + + # Initialize request argument(s) + request = discoveryengine_v1beta.CreateSessionRequest( + parent="parent_value", + ) + + # Make the request + response = client.create_session(request=request) + + # Handle the response + print(response) + +# [END discoveryengine_v1beta_generated_ConversationalSearchService_CreateSession_sync] diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_conversational_search_service_delete_session_async.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_conversational_search_service_delete_session_async.py new file mode 100644 index 000000000000..716121616cbf --- /dev/null +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_conversational_search_service_delete_session_async.py @@ -0,0 +1,50 @@ +# -*- 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 DeleteSession +# 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-discoveryengine + + +# [START discoveryengine_v1beta_generated_ConversationalSearchService_DeleteSession_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 discoveryengine_v1beta + + +async def sample_delete_session(): + # Create a client + client = discoveryengine_v1beta.ConversationalSearchServiceAsyncClient() + + # Initialize request argument(s) + request = discoveryengine_v1beta.DeleteSessionRequest( + name="name_value", + ) + + # Make the request + await client.delete_session(request=request) + + +# [END discoveryengine_v1beta_generated_ConversationalSearchService_DeleteSession_async] diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_conversational_search_service_delete_session_sync.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_conversational_search_service_delete_session_sync.py new file mode 100644 index 000000000000..2ff1fead3d78 --- /dev/null +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_conversational_search_service_delete_session_sync.py @@ -0,0 +1,50 @@ +# -*- 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 DeleteSession +# 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-discoveryengine + + +# [START discoveryengine_v1beta_generated_ConversationalSearchService_DeleteSession_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 discoveryengine_v1beta + + +def sample_delete_session(): + # Create a client + client = discoveryengine_v1beta.ConversationalSearchServiceClient() + + # Initialize request argument(s) + request = discoveryengine_v1beta.DeleteSessionRequest( + name="name_value", + ) + + # Make the request + client.delete_session(request=request) + + +# [END discoveryengine_v1beta_generated_ConversationalSearchService_DeleteSession_sync] diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_conversational_search_service_get_answer_async.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_conversational_search_service_get_answer_async.py new file mode 100644 index 000000000000..0eed12572cec --- /dev/null +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_conversational_search_service_get_answer_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 GetAnswer +# 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-discoveryengine + + +# [START discoveryengine_v1beta_generated_ConversationalSearchService_GetAnswer_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 discoveryengine_v1beta + + +async def sample_get_answer(): + # Create a client + client = discoveryengine_v1beta.ConversationalSearchServiceAsyncClient() + + # Initialize request argument(s) + request = discoveryengine_v1beta.GetAnswerRequest( + name="name_value", + ) + + # Make the request + response = await client.get_answer(request=request) + + # Handle the response + print(response) + +# [END discoveryengine_v1beta_generated_ConversationalSearchService_GetAnswer_async] diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_conversational_search_service_get_answer_sync.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_conversational_search_service_get_answer_sync.py new file mode 100644 index 000000000000..3eebedbd797a --- /dev/null +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_conversational_search_service_get_answer_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 GetAnswer +# 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-discoveryengine + + +# [START discoveryengine_v1beta_generated_ConversationalSearchService_GetAnswer_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 discoveryengine_v1beta + + +def sample_get_answer(): + # Create a client + client = discoveryengine_v1beta.ConversationalSearchServiceClient() + + # Initialize request argument(s) + request = discoveryengine_v1beta.GetAnswerRequest( + name="name_value", + ) + + # Make the request + response = client.get_answer(request=request) + + # Handle the response + print(response) + +# [END discoveryengine_v1beta_generated_ConversationalSearchService_GetAnswer_sync] diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_conversational_search_service_get_session_async.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_conversational_search_service_get_session_async.py new file mode 100644 index 000000000000..052027a2c830 --- /dev/null +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_conversational_search_service_get_session_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 GetSession +# 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-discoveryengine + + +# [START discoveryengine_v1beta_generated_ConversationalSearchService_GetSession_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 discoveryengine_v1beta + + +async def sample_get_session(): + # Create a client + client = discoveryengine_v1beta.ConversationalSearchServiceAsyncClient() + + # Initialize request argument(s) + request = discoveryengine_v1beta.GetSessionRequest( + name="name_value", + ) + + # Make the request + response = await client.get_session(request=request) + + # Handle the response + print(response) + +# [END discoveryengine_v1beta_generated_ConversationalSearchService_GetSession_async] diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_conversational_search_service_get_session_sync.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_conversational_search_service_get_session_sync.py new file mode 100644 index 000000000000..8961655e20a7 --- /dev/null +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_conversational_search_service_get_session_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 GetSession +# 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-discoveryengine + + +# [START discoveryengine_v1beta_generated_ConversationalSearchService_GetSession_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 discoveryengine_v1beta + + +def sample_get_session(): + # Create a client + client = discoveryengine_v1beta.ConversationalSearchServiceClient() + + # Initialize request argument(s) + request = discoveryengine_v1beta.GetSessionRequest( + name="name_value", + ) + + # Make the request + response = client.get_session(request=request) + + # Handle the response + print(response) + +# [END discoveryengine_v1beta_generated_ConversationalSearchService_GetSession_sync] diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_conversational_search_service_list_sessions_async.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_conversational_search_service_list_sessions_async.py new file mode 100644 index 000000000000..25e536da7223 --- /dev/null +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_conversational_search_service_list_sessions_async.py @@ -0,0 +1,53 @@ +# -*- 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 ListSessions +# 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-discoveryengine + + +# [START discoveryengine_v1beta_generated_ConversationalSearchService_ListSessions_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 discoveryengine_v1beta + + +async def sample_list_sessions(): + # Create a client + client = discoveryengine_v1beta.ConversationalSearchServiceAsyncClient() + + # Initialize request argument(s) + request = discoveryengine_v1beta.ListSessionsRequest( + parent="parent_value", + ) + + # Make the request + page_result = client.list_sessions(request=request) + + # Handle the response + async for response in page_result: + print(response) + +# [END discoveryengine_v1beta_generated_ConversationalSearchService_ListSessions_async] diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_conversational_search_service_list_sessions_sync.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_conversational_search_service_list_sessions_sync.py new file mode 100644 index 000000000000..e4aed9d343c9 --- /dev/null +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_conversational_search_service_list_sessions_sync.py @@ -0,0 +1,53 @@ +# -*- 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 ListSessions +# 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-discoveryengine + + +# [START discoveryengine_v1beta_generated_ConversationalSearchService_ListSessions_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 discoveryengine_v1beta + + +def sample_list_sessions(): + # Create a client + client = discoveryengine_v1beta.ConversationalSearchServiceClient() + + # Initialize request argument(s) + request = discoveryengine_v1beta.ListSessionsRequest( + parent="parent_value", + ) + + # Make the request + page_result = client.list_sessions(request=request) + + # Handle the response + for response in page_result: + print(response) + +# [END discoveryengine_v1beta_generated_ConversationalSearchService_ListSessions_sync] diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_conversational_search_service_update_session_async.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_conversational_search_service_update_session_async.py new file mode 100644 index 000000000000..8ef1463acd39 --- /dev/null +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_conversational_search_service_update_session_async.py @@ -0,0 +1,51 @@ +# -*- 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 UpdateSession +# 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-discoveryengine + + +# [START discoveryengine_v1beta_generated_ConversationalSearchService_UpdateSession_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 discoveryengine_v1beta + + +async def sample_update_session(): + # Create a client + client = discoveryengine_v1beta.ConversationalSearchServiceAsyncClient() + + # Initialize request argument(s) + request = discoveryengine_v1beta.UpdateSessionRequest( + ) + + # Make the request + response = await client.update_session(request=request) + + # Handle the response + print(response) + +# [END discoveryengine_v1beta_generated_ConversationalSearchService_UpdateSession_async] diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_conversational_search_service_update_session_sync.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_conversational_search_service_update_session_sync.py new file mode 100644 index 000000000000..b6302cb1ffc7 --- /dev/null +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_conversational_search_service_update_session_sync.py @@ -0,0 +1,51 @@ +# -*- 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 UpdateSession +# 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-discoveryengine + + +# [START discoveryengine_v1beta_generated_ConversationalSearchService_UpdateSession_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 discoveryengine_v1beta + + +def sample_update_session(): + # Create a client + client = discoveryengine_v1beta.ConversationalSearchServiceClient() + + # Initialize request argument(s) + request = discoveryengine_v1beta.UpdateSessionRequest( + ) + + # Make the request + response = client.update_session(request=request) + + # Handle the response + print(response) + +# [END discoveryengine_v1beta_generated_ConversationalSearchService_UpdateSession_sync] diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_engine_service_create_engine_async.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_engine_service_create_engine_async.py index 235921069b54..f5d6bbf54a7a 100644 --- a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_engine_service_create_engine_async.py +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_engine_service_create_engine_async.py @@ -41,7 +41,7 @@ async def sample_create_engine(): # Initialize request argument(s) engine = discoveryengine_v1beta.Engine() engine.display_name = "display_name_value" - engine.solution_type = "SOLUTION_TYPE_CHAT" + engine.solution_type = "SOLUTION_TYPE_GENERATIVE_CHAT" request = discoveryengine_v1beta.CreateEngineRequest( parent="parent_value", diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_engine_service_create_engine_sync.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_engine_service_create_engine_sync.py index 1c809475d646..51f98d3c866c 100644 --- a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_engine_service_create_engine_sync.py +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_engine_service_create_engine_sync.py @@ -41,7 +41,7 @@ def sample_create_engine(): # Initialize request argument(s) engine = discoveryengine_v1beta.Engine() engine.display_name = "display_name_value" - engine.solution_type = "SOLUTION_TYPE_CHAT" + engine.solution_type = "SOLUTION_TYPE_GENERATIVE_CHAT" request = discoveryengine_v1beta.CreateEngineRequest( parent="parent_value", diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_engine_service_pause_engine_async.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_engine_service_pause_engine_async.py new file mode 100644 index 000000000000..7fac85a1f5e6 --- /dev/null +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_engine_service_pause_engine_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 PauseEngine +# 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-discoveryengine + + +# [START discoveryengine_v1beta_generated_EngineService_PauseEngine_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 discoveryengine_v1beta + + +async def sample_pause_engine(): + # Create a client + client = discoveryengine_v1beta.EngineServiceAsyncClient() + + # Initialize request argument(s) + request = discoveryengine_v1beta.PauseEngineRequest( + name="name_value", + ) + + # Make the request + response = await client.pause_engine(request=request) + + # Handle the response + print(response) + +# [END discoveryengine_v1beta_generated_EngineService_PauseEngine_async] diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_engine_service_pause_engine_sync.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_engine_service_pause_engine_sync.py new file mode 100644 index 000000000000..445bf918ee03 --- /dev/null +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_engine_service_pause_engine_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 PauseEngine +# 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-discoveryengine + + +# [START discoveryengine_v1beta_generated_EngineService_PauseEngine_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 discoveryengine_v1beta + + +def sample_pause_engine(): + # Create a client + client = discoveryengine_v1beta.EngineServiceClient() + + # Initialize request argument(s) + request = discoveryengine_v1beta.PauseEngineRequest( + name="name_value", + ) + + # Make the request + response = client.pause_engine(request=request) + + # Handle the response + print(response) + +# [END discoveryengine_v1beta_generated_EngineService_PauseEngine_sync] diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_engine_service_resume_engine_async.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_engine_service_resume_engine_async.py new file mode 100644 index 000000000000..654bf97369d8 --- /dev/null +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_engine_service_resume_engine_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 ResumeEngine +# 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-discoveryengine + + +# [START discoveryengine_v1beta_generated_EngineService_ResumeEngine_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 discoveryengine_v1beta + + +async def sample_resume_engine(): + # Create a client + client = discoveryengine_v1beta.EngineServiceAsyncClient() + + # Initialize request argument(s) + request = discoveryengine_v1beta.ResumeEngineRequest( + name="name_value", + ) + + # Make the request + response = await client.resume_engine(request=request) + + # Handle the response + print(response) + +# [END discoveryengine_v1beta_generated_EngineService_ResumeEngine_async] diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_engine_service_resume_engine_sync.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_engine_service_resume_engine_sync.py new file mode 100644 index 000000000000..2614ce1623ec --- /dev/null +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_engine_service_resume_engine_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 ResumeEngine +# 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-discoveryengine + + +# [START discoveryengine_v1beta_generated_EngineService_ResumeEngine_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 discoveryengine_v1beta + + +def sample_resume_engine(): + # Create a client + client = discoveryengine_v1beta.EngineServiceClient() + + # Initialize request argument(s) + request = discoveryengine_v1beta.ResumeEngineRequest( + name="name_value", + ) + + # Make the request + response = client.resume_engine(request=request) + + # Handle the response + print(response) + +# [END discoveryengine_v1beta_generated_EngineService_ResumeEngine_sync] diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_engine_service_tune_engine_async.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_engine_service_tune_engine_async.py new file mode 100644 index 000000000000..94d20e19cd50 --- /dev/null +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_engine_service_tune_engine_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 TuneEngine +# 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-discoveryengine + + +# [START discoveryengine_v1beta_generated_EngineService_TuneEngine_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 discoveryengine_v1beta + + +async def sample_tune_engine(): + # Create a client + client = discoveryengine_v1beta.EngineServiceAsyncClient() + + # Initialize request argument(s) + request = discoveryengine_v1beta.TuneEngineRequest( + name="name_value", + ) + + # Make the request + operation = client.tune_engine(request=request) + + print("Waiting for operation to complete...") + + response = (await operation).result() + + # Handle the response + print(response) + +# [END discoveryengine_v1beta_generated_EngineService_TuneEngine_async] diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_engine_service_tune_engine_sync.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_engine_service_tune_engine_sync.py new file mode 100644 index 000000000000..e56091e44457 --- /dev/null +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_engine_service_tune_engine_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 TuneEngine +# 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-discoveryengine + + +# [START discoveryengine_v1beta_generated_EngineService_TuneEngine_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 discoveryengine_v1beta + + +def sample_tune_engine(): + # Create a client + client = discoveryengine_v1beta.EngineServiceClient() + + # Initialize request argument(s) + request = discoveryengine_v1beta.TuneEngineRequest( + name="name_value", + ) + + # Make the request + operation = client.tune_engine(request=request) + + print("Waiting for operation to complete...") + + response = operation.result() + + # Handle the response + print(response) + +# [END discoveryengine_v1beta_generated_EngineService_TuneEngine_sync] diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_engine_service_update_engine_async.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_engine_service_update_engine_async.py index 910f84ea17cc..99234566b149 100644 --- a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_engine_service_update_engine_async.py +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_engine_service_update_engine_async.py @@ -41,7 +41,7 @@ async def sample_update_engine(): # Initialize request argument(s) engine = discoveryengine_v1beta.Engine() engine.display_name = "display_name_value" - engine.solution_type = "SOLUTION_TYPE_CHAT" + engine.solution_type = "SOLUTION_TYPE_GENERATIVE_CHAT" request = discoveryengine_v1beta.UpdateEngineRequest( engine=engine, diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_engine_service_update_engine_sync.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_engine_service_update_engine_sync.py index 842a6e4b4b2e..91000ba13cc2 100644 --- a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_engine_service_update_engine_sync.py +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_engine_service_update_engine_sync.py @@ -41,7 +41,7 @@ def sample_update_engine(): # Initialize request argument(s) engine = discoveryengine_v1beta.Engine() engine.display_name = "display_name_value" - engine.solution_type = "SOLUTION_TYPE_CHAT" + engine.solution_type = "SOLUTION_TYPE_GENERATIVE_CHAT" request = discoveryengine_v1beta.UpdateEngineRequest( engine=engine, diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_grounded_generation_service_check_grounding_async.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_grounded_generation_service_check_grounding_async.py new file mode 100644 index 000000000000..c3c13f614694 --- /dev/null +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_grounded_generation_service_check_grounding_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 CheckGrounding +# 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-discoveryengine + + +# [START discoveryengine_v1beta_generated_GroundedGenerationService_CheckGrounding_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 discoveryengine_v1beta + + +async def sample_check_grounding(): + # Create a client + client = discoveryengine_v1beta.GroundedGenerationServiceAsyncClient() + + # Initialize request argument(s) + request = discoveryengine_v1beta.CheckGroundingRequest( + grounding_config="grounding_config_value", + ) + + # Make the request + response = await client.check_grounding(request=request) + + # Handle the response + print(response) + +# [END discoveryengine_v1beta_generated_GroundedGenerationService_CheckGrounding_async] diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_grounded_generation_service_check_grounding_sync.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_grounded_generation_service_check_grounding_sync.py new file mode 100644 index 000000000000..0bb6999e25e6 --- /dev/null +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_grounded_generation_service_check_grounding_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 CheckGrounding +# 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-discoveryengine + + +# [START discoveryengine_v1beta_generated_GroundedGenerationService_CheckGrounding_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 discoveryengine_v1beta + + +def sample_check_grounding(): + # Create a client + client = discoveryengine_v1beta.GroundedGenerationServiceClient() + + # Initialize request argument(s) + request = discoveryengine_v1beta.CheckGroundingRequest( + grounding_config="grounding_config_value", + ) + + # Make the request + response = client.check_grounding(request=request) + + # Handle the response + print(response) + +# [END discoveryengine_v1beta_generated_GroundedGenerationService_CheckGrounding_sync] diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_rank_service_rank_async.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_rank_service_rank_async.py new file mode 100644 index 000000000000..ab7deea949d8 --- /dev/null +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_rank_service_rank_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 Rank +# 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-discoveryengine + + +# [START discoveryengine_v1beta_generated_RankService_Rank_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 discoveryengine_v1beta + + +async def sample_rank(): + # Create a client + client = discoveryengine_v1beta.RankServiceAsyncClient() + + # Initialize request argument(s) + request = discoveryengine_v1beta.RankRequest( + ranking_config="ranking_config_value", + ) + + # Make the request + response = await client.rank(request=request) + + # Handle the response + print(response) + +# [END discoveryengine_v1beta_generated_RankService_Rank_async] diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_rank_service_rank_sync.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_rank_service_rank_sync.py new file mode 100644 index 000000000000..703a7cc1fd33 --- /dev/null +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_rank_service_rank_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 Rank +# 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-discoveryengine + + +# [START discoveryengine_v1beta_generated_RankService_Rank_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 discoveryengine_v1beta + + +def sample_rank(): + # Create a client + client = discoveryengine_v1beta.RankServiceClient() + + # Initialize request argument(s) + request = discoveryengine_v1beta.RankRequest( + ranking_config="ranking_config_value", + ) + + # Make the request + response = client.rank(request=request) + + # Handle the response + print(response) + +# [END discoveryengine_v1beta_generated_RankService_Rank_sync] diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_serving_config_service_update_serving_config_async.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_serving_config_service_update_serving_config_async.py index 443144c684e7..89e6571bd488 100644 --- a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_serving_config_service_update_serving_config_async.py +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_serving_config_service_update_serving_config_async.py @@ -42,7 +42,7 @@ async def sample_update_serving_config(): serving_config = discoveryengine_v1beta.ServingConfig() serving_config.media_config.content_watched_percentage_threshold = 0.3811 serving_config.display_name = "display_name_value" - serving_config.solution_type = "SOLUTION_TYPE_CHAT" + serving_config.solution_type = "SOLUTION_TYPE_GENERATIVE_CHAT" request = discoveryengine_v1beta.UpdateServingConfigRequest( serving_config=serving_config, diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_serving_config_service_update_serving_config_sync.py b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_serving_config_service_update_serving_config_sync.py index da88bff6dc28..0a428e88cb3a 100644 --- a/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_serving_config_service_update_serving_config_sync.py +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_serving_config_service_update_serving_config_sync.py @@ -42,7 +42,7 @@ def sample_update_serving_config(): serving_config = discoveryengine_v1beta.ServingConfig() serving_config.media_config.content_watched_percentage_threshold = 0.3811 serving_config.display_name = "display_name_value" - serving_config.solution_type = "SOLUTION_TYPE_CHAT" + serving_config.solution_type = "SOLUTION_TYPE_GENERATIVE_CHAT" request = discoveryengine_v1beta.UpdateServingConfigRequest( serving_config=serving_config, diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/snippet_metadata_google.cloud.discoveryengine.v1.json b/packages/google-cloud-discoveryengine/samples/generated_samples/snippet_metadata_google.cloud.discoveryengine.v1.json index 61cf4181bdba..21e73dc22511 100644 --- a/packages/google-cloud-discoveryengine/samples/generated_samples/snippet_metadata_google.cloud.discoveryengine.v1.json +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/snippet_metadata_google.cloud.discoveryengine.v1.json @@ -3265,6 +3265,14 @@ "name": "request", "type": "google.cloud.discoveryengine_v1.types.UpdateDocumentRequest" }, + { + "name": "document", + "type": "google.cloud.discoveryengine_v1.types.Document" + }, + { + "name": "update_mask", + "type": "google.protobuf.field_mask_pb2.FieldMask" + }, { "name": "retry", "type": "google.api_core.retry.Retry" @@ -3341,6 +3349,14 @@ "name": "request", "type": "google.cloud.discoveryengine_v1.types.UpdateDocumentRequest" }, + { + "name": "document", + "type": "google.cloud.discoveryengine_v1.types.Document" + }, + { + "name": "update_mask", + "type": "google.protobuf.field_mask_pb2.FieldMask" + }, { "name": "retry", "type": "google.api_core.retry.Retry" @@ -4225,6 +4241,159 @@ ], "title": "discoveryengine_v1_generated_engine_service_update_engine_sync.py" }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.discoveryengine_v1.RecommendationServiceAsyncClient", + "shortName": "RecommendationServiceAsyncClient" + }, + "fullName": "google.cloud.discoveryengine_v1.RecommendationServiceAsyncClient.recommend", + "method": { + "fullName": "google.cloud.discoveryengine.v1.RecommendationService.Recommend", + "service": { + "fullName": "google.cloud.discoveryengine.v1.RecommendationService", + "shortName": "RecommendationService" + }, + "shortName": "Recommend" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.discoveryengine_v1.types.RecommendRequest" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.cloud.discoveryengine_v1.types.RecommendResponse", + "shortName": "recommend" + }, + "description": "Sample for Recommend", + "file": "discoveryengine_v1_generated_recommendation_service_recommend_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "discoveryengine_v1_generated_RecommendationService_Recommend_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": "discoveryengine_v1_generated_recommendation_service_recommend_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.discoveryengine_v1.RecommendationServiceClient", + "shortName": "RecommendationServiceClient" + }, + "fullName": "google.cloud.discoveryengine_v1.RecommendationServiceClient.recommend", + "method": { + "fullName": "google.cloud.discoveryengine.v1.RecommendationService.Recommend", + "service": { + "fullName": "google.cloud.discoveryengine.v1.RecommendationService", + "shortName": "RecommendationService" + }, + "shortName": "Recommend" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.discoveryengine_v1.types.RecommendRequest" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.cloud.discoveryengine_v1.types.RecommendResponse", + "shortName": "recommend" + }, + "description": "Sample for Recommend", + "file": "discoveryengine_v1_generated_recommendation_service_recommend_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "discoveryengine_v1_generated_RecommendationService_Recommend_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": "discoveryengine_v1_generated_recommendation_service_recommend_sync.py" + }, { "canonical": true, "clientMethod": { diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/snippet_metadata_google.cloud.discoveryengine.v1alpha.json b/packages/google-cloud-discoveryengine/samples/generated_samples/snippet_metadata_google.cloud.discoveryengine.v1alpha.json index eed106675397..d424f375fec4 100644 --- a/packages/google-cloud-discoveryengine/samples/generated_samples/snippet_metadata_google.cloud.discoveryengine.v1alpha.json +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/snippet_metadata_google.cloud.discoveryengine.v1alpha.json @@ -1106,6 +1106,159 @@ ], "title": "discoveryengine_v1alpha_generated_completion_service_purge_suggestion_deny_list_entries_sync.py" }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.discoveryengine_v1alpha.ConversationalSearchServiceAsyncClient", + "shortName": "ConversationalSearchServiceAsyncClient" + }, + "fullName": "google.cloud.discoveryengine_v1alpha.ConversationalSearchServiceAsyncClient.answer_query", + "method": { + "fullName": "google.cloud.discoveryengine.v1alpha.ConversationalSearchService.AnswerQuery", + "service": { + "fullName": "google.cloud.discoveryengine.v1alpha.ConversationalSearchService", + "shortName": "ConversationalSearchService" + }, + "shortName": "AnswerQuery" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.discoveryengine_v1alpha.types.AnswerQueryRequest" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.cloud.discoveryengine_v1alpha.types.AnswerQueryResponse", + "shortName": "answer_query" + }, + "description": "Sample for AnswerQuery", + "file": "discoveryengine_v1alpha_generated_conversational_search_service_answer_query_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "discoveryengine_v1alpha_generated_ConversationalSearchService_AnswerQuery_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": "discoveryengine_v1alpha_generated_conversational_search_service_answer_query_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.discoveryengine_v1alpha.ConversationalSearchServiceClient", + "shortName": "ConversationalSearchServiceClient" + }, + "fullName": "google.cloud.discoveryengine_v1alpha.ConversationalSearchServiceClient.answer_query", + "method": { + "fullName": "google.cloud.discoveryengine.v1alpha.ConversationalSearchService.AnswerQuery", + "service": { + "fullName": "google.cloud.discoveryengine.v1alpha.ConversationalSearchService", + "shortName": "ConversationalSearchService" + }, + "shortName": "AnswerQuery" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.discoveryengine_v1alpha.types.AnswerQueryRequest" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.cloud.discoveryengine_v1alpha.types.AnswerQueryResponse", + "shortName": "answer_query" + }, + "description": "Sample for AnswerQuery", + "file": "discoveryengine_v1alpha_generated_conversational_search_service_answer_query_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "discoveryengine_v1alpha_generated_ConversationalSearchService_AnswerQuery_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": "discoveryengine_v1alpha_generated_conversational_search_service_answer_query_sync.py" + }, { "canonical": true, "clientMethod": { @@ -1452,24 +1605,28 @@ "fullName": "google.cloud.discoveryengine_v1alpha.ConversationalSearchServiceAsyncClient", "shortName": "ConversationalSearchServiceAsyncClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.ConversationalSearchServiceAsyncClient.delete_conversation", + "fullName": "google.cloud.discoveryengine_v1alpha.ConversationalSearchServiceAsyncClient.create_session", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.ConversationalSearchService.DeleteConversation", + "fullName": "google.cloud.discoveryengine.v1alpha.ConversationalSearchService.CreateSession", "service": { "fullName": "google.cloud.discoveryengine.v1alpha.ConversationalSearchService", "shortName": "ConversationalSearchService" }, - "shortName": "DeleteConversation" + "shortName": "CreateSession" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.DeleteConversationRequest" + "type": "google.cloud.discoveryengine_v1alpha.types.CreateSessionRequest" }, { - "name": "name", + "name": "parent", "type": "str" }, + { + "name": "session", + "type": "google.cloud.discoveryengine_v1alpha.types.Session" + }, { "name": "retry", "type": "google.api_core.retry.Retry" @@ -1483,21 +1640,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "shortName": "delete_conversation" + "resultType": "google.cloud.discoveryengine_v1alpha.types.Session", + "shortName": "create_session" }, - "description": "Sample for DeleteConversation", - "file": "discoveryengine_v1alpha_generated_conversational_search_service_delete_conversation_async.py", + "description": "Sample for CreateSession", + "file": "discoveryengine_v1alpha_generated_conversational_search_service_create_session_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_ConversationalSearchService_DeleteConversation_async", + "regionTag": "discoveryengine_v1alpha_generated_ConversationalSearchService_CreateSession_async", "segments": [ { - "end": 49, + "end": 51, "start": 27, "type": "FULL" }, { - "end": 49, + "end": 51, "start": 27, "type": "SHORT" }, @@ -1512,15 +1670,17 @@ "type": "REQUEST_INITIALIZATION" }, { + "end": 48, "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 50, + "end": 52, + "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_conversational_search_service_delete_conversation_async.py" + "title": "discoveryengine_v1alpha_generated_conversational_search_service_create_session_async.py" }, { "canonical": true, @@ -1529,24 +1689,28 @@ "fullName": "google.cloud.discoveryengine_v1alpha.ConversationalSearchServiceClient", "shortName": "ConversationalSearchServiceClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.ConversationalSearchServiceClient.delete_conversation", + "fullName": "google.cloud.discoveryengine_v1alpha.ConversationalSearchServiceClient.create_session", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.ConversationalSearchService.DeleteConversation", + "fullName": "google.cloud.discoveryengine.v1alpha.ConversationalSearchService.CreateSession", "service": { "fullName": "google.cloud.discoveryengine.v1alpha.ConversationalSearchService", "shortName": "ConversationalSearchService" }, - "shortName": "DeleteConversation" + "shortName": "CreateSession" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.DeleteConversationRequest" + "type": "google.cloud.discoveryengine_v1alpha.types.CreateSessionRequest" }, { - "name": "name", + "name": "parent", "type": "str" }, + { + "name": "session", + "type": "google.cloud.discoveryengine_v1alpha.types.Session" + }, { "name": "retry", "type": "google.api_core.retry.Retry" @@ -1560,21 +1724,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "shortName": "delete_conversation" + "resultType": "google.cloud.discoveryengine_v1alpha.types.Session", + "shortName": "create_session" }, - "description": "Sample for DeleteConversation", - "file": "discoveryengine_v1alpha_generated_conversational_search_service_delete_conversation_sync.py", + "description": "Sample for CreateSession", + "file": "discoveryengine_v1alpha_generated_conversational_search_service_create_session_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_ConversationalSearchService_DeleteConversation_sync", + "regionTag": "discoveryengine_v1alpha_generated_ConversationalSearchService_CreateSession_sync", "segments": [ { - "end": 49, + "end": 51, "start": 27, "type": "FULL" }, { - "end": 49, + "end": 51, "start": 27, "type": "SHORT" }, @@ -1589,15 +1754,17 @@ "type": "REQUEST_INITIALIZATION" }, { + "end": 48, "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 50, + "end": 52, + "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_conversational_search_service_delete_conversation_sync.py" + "title": "discoveryengine_v1alpha_generated_conversational_search_service_create_session_sync.py" }, { "canonical": true, @@ -1607,19 +1774,19 @@ "fullName": "google.cloud.discoveryengine_v1alpha.ConversationalSearchServiceAsyncClient", "shortName": "ConversationalSearchServiceAsyncClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.ConversationalSearchServiceAsyncClient.get_conversation", + "fullName": "google.cloud.discoveryengine_v1alpha.ConversationalSearchServiceAsyncClient.delete_conversation", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.ConversationalSearchService.GetConversation", + "fullName": "google.cloud.discoveryengine.v1alpha.ConversationalSearchService.DeleteConversation", "service": { "fullName": "google.cloud.discoveryengine.v1alpha.ConversationalSearchService", "shortName": "ConversationalSearchService" }, - "shortName": "GetConversation" + "shortName": "DeleteConversation" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.GetConversationRequest" + "type": "google.cloud.discoveryengine_v1alpha.types.DeleteConversationRequest" }, { "name": "name", @@ -1638,22 +1805,21 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1alpha.types.Conversation", - "shortName": "get_conversation" + "shortName": "delete_conversation" }, - "description": "Sample for GetConversation", - "file": "discoveryengine_v1alpha_generated_conversational_search_service_get_conversation_async.py", + "description": "Sample for DeleteConversation", + "file": "discoveryengine_v1alpha_generated_conversational_search_service_delete_conversation_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_ConversationalSearchService_GetConversation_async", + "regionTag": "discoveryengine_v1alpha_generated_ConversationalSearchService_DeleteConversation_async", "segments": [ { - "end": 51, + "end": 49, "start": 27, "type": "FULL" }, { - "end": 51, + "end": 49, "start": 27, "type": "SHORT" }, @@ -1668,17 +1834,15 @@ "type": "REQUEST_INITIALIZATION" }, { - "end": 48, "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 52, - "start": 49, + "end": 50, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_conversational_search_service_get_conversation_async.py" + "title": "discoveryengine_v1alpha_generated_conversational_search_service_delete_conversation_async.py" }, { "canonical": true, @@ -1687,19 +1851,19 @@ "fullName": "google.cloud.discoveryengine_v1alpha.ConversationalSearchServiceClient", "shortName": "ConversationalSearchServiceClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.ConversationalSearchServiceClient.get_conversation", + "fullName": "google.cloud.discoveryengine_v1alpha.ConversationalSearchServiceClient.delete_conversation", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.ConversationalSearchService.GetConversation", + "fullName": "google.cloud.discoveryengine.v1alpha.ConversationalSearchService.DeleteConversation", "service": { "fullName": "google.cloud.discoveryengine.v1alpha.ConversationalSearchService", "shortName": "ConversationalSearchService" }, - "shortName": "GetConversation" + "shortName": "DeleteConversation" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.GetConversationRequest" + "type": "google.cloud.discoveryengine_v1alpha.types.DeleteConversationRequest" }, { "name": "name", @@ -1718,22 +1882,21 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1alpha.types.Conversation", - "shortName": "get_conversation" + "shortName": "delete_conversation" }, - "description": "Sample for GetConversation", - "file": "discoveryengine_v1alpha_generated_conversational_search_service_get_conversation_sync.py", + "description": "Sample for DeleteConversation", + "file": "discoveryengine_v1alpha_generated_conversational_search_service_delete_conversation_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_ConversationalSearchService_GetConversation_sync", + "regionTag": "discoveryengine_v1alpha_generated_ConversationalSearchService_DeleteConversation_sync", "segments": [ { - "end": 51, + "end": 49, "start": 27, "type": "FULL" }, { - "end": 51, + "end": 49, "start": 27, "type": "SHORT" }, @@ -1748,17 +1911,15 @@ "type": "REQUEST_INITIALIZATION" }, { - "end": 48, "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 52, - "start": 49, + "end": 50, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_conversational_search_service_get_conversation_sync.py" + "title": "discoveryengine_v1alpha_generated_conversational_search_service_delete_conversation_sync.py" }, { "canonical": true, @@ -1768,22 +1929,22 @@ "fullName": "google.cloud.discoveryengine_v1alpha.ConversationalSearchServiceAsyncClient", "shortName": "ConversationalSearchServiceAsyncClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.ConversationalSearchServiceAsyncClient.list_conversations", + "fullName": "google.cloud.discoveryengine_v1alpha.ConversationalSearchServiceAsyncClient.delete_session", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.ConversationalSearchService.ListConversations", + "fullName": "google.cloud.discoveryengine.v1alpha.ConversationalSearchService.DeleteSession", "service": { "fullName": "google.cloud.discoveryengine.v1alpha.ConversationalSearchService", "shortName": "ConversationalSearchService" }, - "shortName": "ListConversations" + "shortName": "DeleteSession" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.ListConversationsRequest" + "type": "google.cloud.discoveryengine_v1alpha.types.DeleteSessionRequest" }, { - "name": "parent", + "name": "name", "type": "str" }, { @@ -1799,22 +1960,21 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1alpha.services.conversational_search_service.pagers.ListConversationsAsyncPager", - "shortName": "list_conversations" + "shortName": "delete_session" }, - "description": "Sample for ListConversations", - "file": "discoveryengine_v1alpha_generated_conversational_search_service_list_conversations_async.py", + "description": "Sample for DeleteSession", + "file": "discoveryengine_v1alpha_generated_conversational_search_service_delete_session_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_ConversationalSearchService_ListConversations_async", + "regionTag": "discoveryengine_v1alpha_generated_ConversationalSearchService_DeleteSession_async", "segments": [ { - "end": 52, + "end": 49, "start": 27, "type": "FULL" }, { - "end": 52, + "end": 49, "start": 27, "type": "SHORT" }, @@ -1829,17 +1989,15 @@ "type": "REQUEST_INITIALIZATION" }, { - "end": 48, "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 53, - "start": 49, + "end": 50, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_conversational_search_service_list_conversations_async.py" + "title": "discoveryengine_v1alpha_generated_conversational_search_service_delete_session_async.py" }, { "canonical": true, @@ -1848,22 +2006,22 @@ "fullName": "google.cloud.discoveryengine_v1alpha.ConversationalSearchServiceClient", "shortName": "ConversationalSearchServiceClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.ConversationalSearchServiceClient.list_conversations", + "fullName": "google.cloud.discoveryengine_v1alpha.ConversationalSearchServiceClient.delete_session", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.ConversationalSearchService.ListConversations", + "fullName": "google.cloud.discoveryengine.v1alpha.ConversationalSearchService.DeleteSession", "service": { "fullName": "google.cloud.discoveryengine.v1alpha.ConversationalSearchService", "shortName": "ConversationalSearchService" }, - "shortName": "ListConversations" + "shortName": "DeleteSession" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.ListConversationsRequest" + "type": "google.cloud.discoveryengine_v1alpha.types.DeleteSessionRequest" }, { - "name": "parent", + "name": "name", "type": "str" }, { @@ -1879,22 +2037,21 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1alpha.services.conversational_search_service.pagers.ListConversationsPager", - "shortName": "list_conversations" + "shortName": "delete_session" }, - "description": "Sample for ListConversations", - "file": "discoveryengine_v1alpha_generated_conversational_search_service_list_conversations_sync.py", + "description": "Sample for DeleteSession", + "file": "discoveryengine_v1alpha_generated_conversational_search_service_delete_session_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_ConversationalSearchService_ListConversations_sync", + "regionTag": "discoveryengine_v1alpha_generated_ConversationalSearchService_DeleteSession_sync", "segments": [ { - "end": 52, + "end": 49, "start": 27, "type": "FULL" }, { - "end": 52, + "end": 49, "start": 27, "type": "SHORT" }, @@ -1909,17 +2066,15 @@ "type": "REQUEST_INITIALIZATION" }, { - "end": 48, "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 53, - "start": 49, + "end": 50, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_conversational_search_service_list_conversations_sync.py" + "title": "discoveryengine_v1alpha_generated_conversational_search_service_delete_session_sync.py" }, { "canonical": true, @@ -1929,27 +2084,23 @@ "fullName": "google.cloud.discoveryengine_v1alpha.ConversationalSearchServiceAsyncClient", "shortName": "ConversationalSearchServiceAsyncClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.ConversationalSearchServiceAsyncClient.update_conversation", + "fullName": "google.cloud.discoveryengine_v1alpha.ConversationalSearchServiceAsyncClient.get_answer", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.ConversationalSearchService.UpdateConversation", + "fullName": "google.cloud.discoveryengine.v1alpha.ConversationalSearchService.GetAnswer", "service": { "fullName": "google.cloud.discoveryengine.v1alpha.ConversationalSearchService", "shortName": "ConversationalSearchService" }, - "shortName": "UpdateConversation" + "shortName": "GetAnswer" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.UpdateConversationRequest" - }, - { - "name": "conversation", - "type": "google.cloud.discoveryengine_v1alpha.types.Conversation" + "type": "google.cloud.discoveryengine_v1alpha.types.GetAnswerRequest" }, { - "name": "update_mask", - "type": "google.protobuf.field_mask_pb2.FieldMask" + "name": "name", + "type": "str" }, { "name": "retry", @@ -1964,22 +2115,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1alpha.types.Conversation", - "shortName": "update_conversation" + "resultType": "google.cloud.discoveryengine_v1alpha.types.Answer", + "shortName": "get_answer" }, - "description": "Sample for UpdateConversation", - "file": "discoveryengine_v1alpha_generated_conversational_search_service_update_conversation_async.py", + "description": "Sample for GetAnswer", + "file": "discoveryengine_v1alpha_generated_conversational_search_service_get_answer_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_ConversationalSearchService_UpdateConversation_async", + "regionTag": "discoveryengine_v1alpha_generated_ConversationalSearchService_GetAnswer_async", "segments": [ { - "end": 50, + "end": 51, "start": 27, "type": "FULL" }, { - "end": 50, + "end": 51, "start": 27, "type": "SHORT" }, @@ -1989,22 +2140,22 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 44, + "end": 45, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 47, - "start": 45, + "end": 48, + "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 51, - "start": 48, + "end": 52, + "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_conversational_search_service_update_conversation_async.py" + "title": "discoveryengine_v1alpha_generated_conversational_search_service_get_answer_async.py" }, { "canonical": true, @@ -2013,27 +2164,23 @@ "fullName": "google.cloud.discoveryengine_v1alpha.ConversationalSearchServiceClient", "shortName": "ConversationalSearchServiceClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.ConversationalSearchServiceClient.update_conversation", + "fullName": "google.cloud.discoveryengine_v1alpha.ConversationalSearchServiceClient.get_answer", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.ConversationalSearchService.UpdateConversation", + "fullName": "google.cloud.discoveryengine.v1alpha.ConversationalSearchService.GetAnswer", "service": { "fullName": "google.cloud.discoveryengine.v1alpha.ConversationalSearchService", "shortName": "ConversationalSearchService" }, - "shortName": "UpdateConversation" + "shortName": "GetAnswer" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.UpdateConversationRequest" - }, - { - "name": "conversation", - "type": "google.cloud.discoveryengine_v1alpha.types.Conversation" + "type": "google.cloud.discoveryengine_v1alpha.types.GetAnswerRequest" }, { - "name": "update_mask", - "type": "google.protobuf.field_mask_pb2.FieldMask" + "name": "name", + "type": "str" }, { "name": "retry", @@ -2048,22 +2195,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1alpha.types.Conversation", - "shortName": "update_conversation" + "resultType": "google.cloud.discoveryengine_v1alpha.types.Answer", + "shortName": "get_answer" }, - "description": "Sample for UpdateConversation", - "file": "discoveryengine_v1alpha_generated_conversational_search_service_update_conversation_sync.py", + "description": "Sample for GetAnswer", + "file": "discoveryengine_v1alpha_generated_conversational_search_service_get_answer_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_ConversationalSearchService_UpdateConversation_sync", + "regionTag": "discoveryengine_v1alpha_generated_ConversationalSearchService_GetAnswer_sync", "segments": [ { - "end": 50, + "end": 51, "start": 27, "type": "FULL" }, { - "end": 50, + "end": 51, "start": 27, "type": "SHORT" }, @@ -2073,55 +2220,47 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 44, + "end": 45, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 47, - "start": 45, + "end": 48, + "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 51, - "start": 48, + "end": 52, + "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_conversational_search_service_update_conversation_sync.py" + "title": "discoveryengine_v1alpha_generated_conversational_search_service_get_answer_sync.py" }, { "canonical": true, "clientMethod": { "async": true, "client": { - "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceAsyncClient", - "shortName": "DataStoreServiceAsyncClient" + "fullName": "google.cloud.discoveryengine_v1alpha.ConversationalSearchServiceAsyncClient", + "shortName": "ConversationalSearchServiceAsyncClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceAsyncClient.create_data_store", + "fullName": "google.cloud.discoveryengine_v1alpha.ConversationalSearchServiceAsyncClient.get_conversation", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService.CreateDataStore", + "fullName": "google.cloud.discoveryengine.v1alpha.ConversationalSearchService.GetConversation", "service": { - "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService", - "shortName": "DataStoreService" + "fullName": "google.cloud.discoveryengine.v1alpha.ConversationalSearchService", + "shortName": "ConversationalSearchService" }, - "shortName": "CreateDataStore" + "shortName": "GetConversation" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.CreateDataStoreRequest" - }, - { - "name": "parent", - "type": "str" - }, - { - "name": "data_store", - "type": "google.cloud.discoveryengine_v1alpha.types.DataStore" + "type": "google.cloud.discoveryengine_v1alpha.types.GetConversationRequest" }, { - "name": "data_store_id", + "name": "name", "type": "str" }, { @@ -2137,22 +2276,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.api_core.operation_async.AsyncOperation", - "shortName": "create_data_store" + "resultType": "google.cloud.discoveryengine_v1alpha.types.Conversation", + "shortName": "get_conversation" }, - "description": "Sample for CreateDataStore", - "file": "discoveryengine_v1alpha_generated_data_store_service_create_data_store_async.py", + "description": "Sample for GetConversation", + "file": "discoveryengine_v1alpha_generated_conversational_search_service_get_conversation_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_DataStoreService_CreateDataStore_async", + "regionTag": "discoveryengine_v1alpha_generated_ConversationalSearchService_GetConversation_async", "segments": [ { - "end": 60, + "end": 51, "start": 27, "type": "FULL" }, { - "end": 60, + "end": 51, "start": 27, "type": "SHORT" }, @@ -2162,54 +2301,46 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 50, + "end": 45, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 57, - "start": 51, + "end": 48, + "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 61, - "start": 58, + "end": 52, + "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_data_store_service_create_data_store_async.py" + "title": "discoveryengine_v1alpha_generated_conversational_search_service_get_conversation_async.py" }, { "canonical": true, "clientMethod": { "client": { - "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceClient", - "shortName": "DataStoreServiceClient" + "fullName": "google.cloud.discoveryengine_v1alpha.ConversationalSearchServiceClient", + "shortName": "ConversationalSearchServiceClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceClient.create_data_store", + "fullName": "google.cloud.discoveryengine_v1alpha.ConversationalSearchServiceClient.get_conversation", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService.CreateDataStore", + "fullName": "google.cloud.discoveryengine.v1alpha.ConversationalSearchService.GetConversation", "service": { - "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService", - "shortName": "DataStoreService" + "fullName": "google.cloud.discoveryengine.v1alpha.ConversationalSearchService", + "shortName": "ConversationalSearchService" }, - "shortName": "CreateDataStore" + "shortName": "GetConversation" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.CreateDataStoreRequest" - }, - { - "name": "parent", - "type": "str" - }, - { - "name": "data_store", - "type": "google.cloud.discoveryengine_v1alpha.types.DataStore" + "type": "google.cloud.discoveryengine_v1alpha.types.GetConversationRequest" }, { - "name": "data_store_id", + "name": "name", "type": "str" }, { @@ -2225,22 +2356,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.api_core.operation.Operation", - "shortName": "create_data_store" + "resultType": "google.cloud.discoveryengine_v1alpha.types.Conversation", + "shortName": "get_conversation" }, - "description": "Sample for CreateDataStore", - "file": "discoveryengine_v1alpha_generated_data_store_service_create_data_store_sync.py", + "description": "Sample for GetConversation", + "file": "discoveryengine_v1alpha_generated_conversational_search_service_get_conversation_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_DataStoreService_CreateDataStore_sync", + "regionTag": "discoveryengine_v1alpha_generated_ConversationalSearchService_GetConversation_sync", "segments": [ { - "end": 60, + "end": 51, "start": 27, "type": "FULL" }, { - "end": 60, + "end": 51, "start": 27, "type": "SHORT" }, @@ -2250,44 +2381,44 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 50, + "end": 45, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 57, - "start": 51, + "end": 48, + "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 61, - "start": 58, + "end": 52, + "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_data_store_service_create_data_store_sync.py" + "title": "discoveryengine_v1alpha_generated_conversational_search_service_get_conversation_sync.py" }, { "canonical": true, "clientMethod": { "async": true, "client": { - "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceAsyncClient", - "shortName": "DataStoreServiceAsyncClient" + "fullName": "google.cloud.discoveryengine_v1alpha.ConversationalSearchServiceAsyncClient", + "shortName": "ConversationalSearchServiceAsyncClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceAsyncClient.delete_data_store", + "fullName": "google.cloud.discoveryengine_v1alpha.ConversationalSearchServiceAsyncClient.get_session", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService.DeleteDataStore", + "fullName": "google.cloud.discoveryengine.v1alpha.ConversationalSearchService.GetSession", "service": { - "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService", - "shortName": "DataStoreService" + "fullName": "google.cloud.discoveryengine.v1alpha.ConversationalSearchService", + "shortName": "ConversationalSearchService" }, - "shortName": "DeleteDataStore" + "shortName": "GetSession" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.DeleteDataStoreRequest" + "type": "google.cloud.discoveryengine_v1alpha.types.GetSessionRequest" }, { "name": "name", @@ -2306,22 +2437,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.api_core.operation_async.AsyncOperation", - "shortName": "delete_data_store" + "resultType": "google.cloud.discoveryengine_v1alpha.types.Session", + "shortName": "get_session" }, - "description": "Sample for DeleteDataStore", - "file": "discoveryengine_v1alpha_generated_data_store_service_delete_data_store_async.py", + "description": "Sample for GetSession", + "file": "discoveryengine_v1alpha_generated_conversational_search_service_get_session_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_DataStoreService_DeleteDataStore_async", + "regionTag": "discoveryengine_v1alpha_generated_ConversationalSearchService_GetSession_async", "segments": [ { - "end": 55, + "end": 51, "start": 27, "type": "FULL" }, { - "end": 55, + "end": 51, "start": 27, "type": "SHORT" }, @@ -2336,38 +2467,38 @@ "type": "REQUEST_INITIALIZATION" }, { - "end": 52, + "end": 48, "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 56, - "start": 53, + "end": 52, + "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_data_store_service_delete_data_store_async.py" + "title": "discoveryengine_v1alpha_generated_conversational_search_service_get_session_async.py" }, { "canonical": true, "clientMethod": { "client": { - "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceClient", - "shortName": "DataStoreServiceClient" + "fullName": "google.cloud.discoveryengine_v1alpha.ConversationalSearchServiceClient", + "shortName": "ConversationalSearchServiceClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceClient.delete_data_store", + "fullName": "google.cloud.discoveryengine_v1alpha.ConversationalSearchServiceClient.get_session", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService.DeleteDataStore", + "fullName": "google.cloud.discoveryengine.v1alpha.ConversationalSearchService.GetSession", "service": { - "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService", - "shortName": "DataStoreService" + "fullName": "google.cloud.discoveryengine.v1alpha.ConversationalSearchService", + "shortName": "ConversationalSearchService" }, - "shortName": "DeleteDataStore" + "shortName": "GetSession" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.DeleteDataStoreRequest" + "type": "google.cloud.discoveryengine_v1alpha.types.GetSessionRequest" }, { "name": "name", @@ -2386,22 +2517,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.api_core.operation.Operation", - "shortName": "delete_data_store" + "resultType": "google.cloud.discoveryengine_v1alpha.types.Session", + "shortName": "get_session" }, - "description": "Sample for DeleteDataStore", - "file": "discoveryengine_v1alpha_generated_data_store_service_delete_data_store_sync.py", + "description": "Sample for GetSession", + "file": "discoveryengine_v1alpha_generated_conversational_search_service_get_session_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_DataStoreService_DeleteDataStore_sync", + "regionTag": "discoveryengine_v1alpha_generated_ConversationalSearchService_GetSession_sync", "segments": [ { - "end": 55, + "end": 51, "start": 27, "type": "FULL" }, { - "end": 55, + "end": 51, "start": 27, "type": "SHORT" }, @@ -2416,42 +2547,42 @@ "type": "REQUEST_INITIALIZATION" }, { - "end": 52, + "end": 48, "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 56, - "start": 53, + "end": 52, + "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_data_store_service_delete_data_store_sync.py" + "title": "discoveryengine_v1alpha_generated_conversational_search_service_get_session_sync.py" }, { "canonical": true, "clientMethod": { "async": true, "client": { - "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceAsyncClient", - "shortName": "DataStoreServiceAsyncClient" + "fullName": "google.cloud.discoveryengine_v1alpha.ConversationalSearchServiceAsyncClient", + "shortName": "ConversationalSearchServiceAsyncClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceAsyncClient.get_data_store", + "fullName": "google.cloud.discoveryengine_v1alpha.ConversationalSearchServiceAsyncClient.list_conversations", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService.GetDataStore", + "fullName": "google.cloud.discoveryengine.v1alpha.ConversationalSearchService.ListConversations", "service": { - "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService", - "shortName": "DataStoreService" + "fullName": "google.cloud.discoveryengine.v1alpha.ConversationalSearchService", + "shortName": "ConversationalSearchService" }, - "shortName": "GetDataStore" + "shortName": "ListConversations" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.GetDataStoreRequest" + "type": "google.cloud.discoveryengine_v1alpha.types.ListConversationsRequest" }, { - "name": "name", + "name": "parent", "type": "str" }, { @@ -2467,22 +2598,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1alpha.types.DataStore", - "shortName": "get_data_store" + "resultType": "google.cloud.discoveryengine_v1alpha.services.conversational_search_service.pagers.ListConversationsAsyncPager", + "shortName": "list_conversations" }, - "description": "Sample for GetDataStore", - "file": "discoveryengine_v1alpha_generated_data_store_service_get_data_store_async.py", + "description": "Sample for ListConversations", + "file": "discoveryengine_v1alpha_generated_conversational_search_service_list_conversations_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_DataStoreService_GetDataStore_async", + "regionTag": "discoveryengine_v1alpha_generated_ConversationalSearchService_ListConversations_async", "segments": [ { - "end": 51, + "end": 52, "start": 27, "type": "FULL" }, { - "end": 51, + "end": 52, "start": 27, "type": "SHORT" }, @@ -2502,36 +2633,36 @@ "type": "REQUEST_EXECUTION" }, { - "end": 52, + "end": 53, "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_data_store_service_get_data_store_async.py" + "title": "discoveryengine_v1alpha_generated_conversational_search_service_list_conversations_async.py" }, { "canonical": true, "clientMethod": { "client": { - "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceClient", - "shortName": "DataStoreServiceClient" + "fullName": "google.cloud.discoveryengine_v1alpha.ConversationalSearchServiceClient", + "shortName": "ConversationalSearchServiceClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceClient.get_data_store", + "fullName": "google.cloud.discoveryengine_v1alpha.ConversationalSearchServiceClient.list_conversations", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService.GetDataStore", + "fullName": "google.cloud.discoveryengine.v1alpha.ConversationalSearchService.ListConversations", "service": { - "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService", - "shortName": "DataStoreService" + "fullName": "google.cloud.discoveryengine.v1alpha.ConversationalSearchService", + "shortName": "ConversationalSearchService" }, - "shortName": "GetDataStore" + "shortName": "ListConversations" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.GetDataStoreRequest" + "type": "google.cloud.discoveryengine_v1alpha.types.ListConversationsRequest" }, { - "name": "name", + "name": "parent", "type": "str" }, { @@ -2547,22 +2678,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1alpha.types.DataStore", - "shortName": "get_data_store" + "resultType": "google.cloud.discoveryengine_v1alpha.services.conversational_search_service.pagers.ListConversationsPager", + "shortName": "list_conversations" }, - "description": "Sample for GetDataStore", - "file": "discoveryengine_v1alpha_generated_data_store_service_get_data_store_sync.py", + "description": "Sample for ListConversations", + "file": "discoveryengine_v1alpha_generated_conversational_search_service_list_conversations_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_DataStoreService_GetDataStore_sync", + "regionTag": "discoveryengine_v1alpha_generated_ConversationalSearchService_ListConversations_sync", "segments": [ { - "end": 51, + "end": 52, "start": 27, "type": "FULL" }, { - "end": 51, + "end": 52, "start": 27, "type": "SHORT" }, @@ -2582,37 +2713,37 @@ "type": "REQUEST_EXECUTION" }, { - "end": 52, + "end": 53, "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_data_store_service_get_data_store_sync.py" + "title": "discoveryengine_v1alpha_generated_conversational_search_service_list_conversations_sync.py" }, { "canonical": true, "clientMethod": { "async": true, "client": { - "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceAsyncClient", - "shortName": "DataStoreServiceAsyncClient" + "fullName": "google.cloud.discoveryengine_v1alpha.ConversationalSearchServiceAsyncClient", + "shortName": "ConversationalSearchServiceAsyncClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceAsyncClient.get_document_processing_config", + "fullName": "google.cloud.discoveryengine_v1alpha.ConversationalSearchServiceAsyncClient.list_sessions", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService.GetDocumentProcessingConfig", + "fullName": "google.cloud.discoveryengine.v1alpha.ConversationalSearchService.ListSessions", "service": { - "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService", - "shortName": "DataStoreService" + "fullName": "google.cloud.discoveryengine.v1alpha.ConversationalSearchService", + "shortName": "ConversationalSearchService" }, - "shortName": "GetDocumentProcessingConfig" + "shortName": "ListSessions" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.GetDocumentProcessingConfigRequest" + "type": "google.cloud.discoveryengine_v1alpha.types.ListSessionsRequest" }, { - "name": "name", + "name": "parent", "type": "str" }, { @@ -2628,22 +2759,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1alpha.types.DocumentProcessingConfig", - "shortName": "get_document_processing_config" + "resultType": "google.cloud.discoveryengine_v1alpha.services.conversational_search_service.pagers.ListSessionsAsyncPager", + "shortName": "list_sessions" }, - "description": "Sample for GetDocumentProcessingConfig", - "file": "discoveryengine_v1alpha_generated_data_store_service_get_document_processing_config_async.py", + "description": "Sample for ListSessions", + "file": "discoveryengine_v1alpha_generated_conversational_search_service_list_sessions_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_DataStoreService_GetDocumentProcessingConfig_async", + "regionTag": "discoveryengine_v1alpha_generated_ConversationalSearchService_ListSessions_async", "segments": [ { - "end": 51, + "end": 52, "start": 27, "type": "FULL" }, { - "end": 51, + "end": 52, "start": 27, "type": "SHORT" }, @@ -2663,36 +2794,36 @@ "type": "REQUEST_EXECUTION" }, { - "end": 52, + "end": 53, "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_data_store_service_get_document_processing_config_async.py" + "title": "discoveryengine_v1alpha_generated_conversational_search_service_list_sessions_async.py" }, { "canonical": true, "clientMethod": { "client": { - "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceClient", - "shortName": "DataStoreServiceClient" + "fullName": "google.cloud.discoveryengine_v1alpha.ConversationalSearchServiceClient", + "shortName": "ConversationalSearchServiceClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceClient.get_document_processing_config", + "fullName": "google.cloud.discoveryengine_v1alpha.ConversationalSearchServiceClient.list_sessions", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService.GetDocumentProcessingConfig", + "fullName": "google.cloud.discoveryengine.v1alpha.ConversationalSearchService.ListSessions", "service": { - "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService", - "shortName": "DataStoreService" + "fullName": "google.cloud.discoveryengine.v1alpha.ConversationalSearchService", + "shortName": "ConversationalSearchService" }, - "shortName": "GetDocumentProcessingConfig" + "shortName": "ListSessions" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.GetDocumentProcessingConfigRequest" + "type": "google.cloud.discoveryengine_v1alpha.types.ListSessionsRequest" }, { - "name": "name", + "name": "parent", "type": "str" }, { @@ -2708,22 +2839,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1alpha.types.DocumentProcessingConfig", - "shortName": "get_document_processing_config" + "resultType": "google.cloud.discoveryengine_v1alpha.services.conversational_search_service.pagers.ListSessionsPager", + "shortName": "list_sessions" }, - "description": "Sample for GetDocumentProcessingConfig", - "file": "discoveryengine_v1alpha_generated_data_store_service_get_document_processing_config_sync.py", + "description": "Sample for ListSessions", + "file": "discoveryengine_v1alpha_generated_conversational_search_service_list_sessions_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_DataStoreService_GetDocumentProcessingConfig_sync", + "regionTag": "discoveryengine_v1alpha_generated_ConversationalSearchService_ListSessions_sync", "segments": [ { - "end": 51, + "end": 52, "start": 27, "type": "FULL" }, { - "end": 51, + "end": 52, "start": 27, "type": "SHORT" }, @@ -2743,38 +2874,42 @@ "type": "REQUEST_EXECUTION" }, { - "end": 52, + "end": 53, "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_data_store_service_get_document_processing_config_sync.py" + "title": "discoveryengine_v1alpha_generated_conversational_search_service_list_sessions_sync.py" }, { "canonical": true, "clientMethod": { "async": true, "client": { - "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceAsyncClient", - "shortName": "DataStoreServiceAsyncClient" + "fullName": "google.cloud.discoveryengine_v1alpha.ConversationalSearchServiceAsyncClient", + "shortName": "ConversationalSearchServiceAsyncClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceAsyncClient.list_data_stores", + "fullName": "google.cloud.discoveryengine_v1alpha.ConversationalSearchServiceAsyncClient.update_conversation", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService.ListDataStores", + "fullName": "google.cloud.discoveryengine.v1alpha.ConversationalSearchService.UpdateConversation", "service": { - "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService", - "shortName": "DataStoreService" + "fullName": "google.cloud.discoveryengine.v1alpha.ConversationalSearchService", + "shortName": "ConversationalSearchService" }, - "shortName": "ListDataStores" + "shortName": "UpdateConversation" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.ListDataStoresRequest" + "type": "google.cloud.discoveryengine_v1alpha.types.UpdateConversationRequest" }, { - "name": "parent", - "type": "str" + "name": "conversation", + "type": "google.cloud.discoveryengine_v1alpha.types.Conversation" + }, + { + "name": "update_mask", + "type": "google.protobuf.field_mask_pb2.FieldMask" }, { "name": "retry", @@ -2789,22 +2924,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1alpha.services.data_store_service.pagers.ListDataStoresAsyncPager", - "shortName": "list_data_stores" + "resultType": "google.cloud.discoveryengine_v1alpha.types.Conversation", + "shortName": "update_conversation" }, - "description": "Sample for ListDataStores", - "file": "discoveryengine_v1alpha_generated_data_store_service_list_data_stores_async.py", + "description": "Sample for UpdateConversation", + "file": "discoveryengine_v1alpha_generated_conversational_search_service_update_conversation_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_DataStoreService_ListDataStores_async", + "regionTag": "discoveryengine_v1alpha_generated_ConversationalSearchService_UpdateConversation_async", "segments": [ { - "end": 52, + "end": 50, "start": 27, "type": "FULL" }, { - "end": 52, + "end": 50, "start": 27, "type": "SHORT" }, @@ -2814,47 +2949,51 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 45, + "end": 44, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 48, - "start": 46, + "end": 47, + "start": 45, "type": "REQUEST_EXECUTION" }, { - "end": 53, - "start": 49, + "end": 51, + "start": 48, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_data_store_service_list_data_stores_async.py" + "title": "discoveryengine_v1alpha_generated_conversational_search_service_update_conversation_async.py" }, { "canonical": true, "clientMethod": { "client": { - "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceClient", - "shortName": "DataStoreServiceClient" + "fullName": "google.cloud.discoveryengine_v1alpha.ConversationalSearchServiceClient", + "shortName": "ConversationalSearchServiceClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceClient.list_data_stores", + "fullName": "google.cloud.discoveryengine_v1alpha.ConversationalSearchServiceClient.update_conversation", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService.ListDataStores", + "fullName": "google.cloud.discoveryengine.v1alpha.ConversationalSearchService.UpdateConversation", "service": { - "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService", - "shortName": "DataStoreService" + "fullName": "google.cloud.discoveryengine.v1alpha.ConversationalSearchService", + "shortName": "ConversationalSearchService" }, - "shortName": "ListDataStores" + "shortName": "UpdateConversation" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.ListDataStoresRequest" + "type": "google.cloud.discoveryengine_v1alpha.types.UpdateConversationRequest" }, { - "name": "parent", - "type": "str" + "name": "conversation", + "type": "google.cloud.discoveryengine_v1alpha.types.Conversation" + }, + { + "name": "update_mask", + "type": "google.protobuf.field_mask_pb2.FieldMask" }, { "name": "retry", @@ -2869,22 +3008,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1alpha.services.data_store_service.pagers.ListDataStoresPager", - "shortName": "list_data_stores" + "resultType": "google.cloud.discoveryengine_v1alpha.types.Conversation", + "shortName": "update_conversation" }, - "description": "Sample for ListDataStores", - "file": "discoveryengine_v1alpha_generated_data_store_service_list_data_stores_sync.py", + "description": "Sample for UpdateConversation", + "file": "discoveryengine_v1alpha_generated_conversational_search_service_update_conversation_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_DataStoreService_ListDataStores_sync", + "regionTag": "discoveryengine_v1alpha_generated_ConversationalSearchService_UpdateConversation_sync", "segments": [ { - "end": 52, + "end": 50, "start": 27, "type": "FULL" }, { - "end": 52, + "end": 50, "start": 27, "type": "SHORT" }, @@ -2894,48 +3033,48 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 45, + "end": 44, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 48, - "start": 46, + "end": 47, + "start": 45, "type": "REQUEST_EXECUTION" }, { - "end": 53, - "start": 49, + "end": 51, + "start": 48, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_data_store_service_list_data_stores_sync.py" + "title": "discoveryengine_v1alpha_generated_conversational_search_service_update_conversation_sync.py" }, { "canonical": true, "clientMethod": { "async": true, "client": { - "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceAsyncClient", - "shortName": "DataStoreServiceAsyncClient" + "fullName": "google.cloud.discoveryengine_v1alpha.ConversationalSearchServiceAsyncClient", + "shortName": "ConversationalSearchServiceAsyncClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceAsyncClient.update_data_store", + "fullName": "google.cloud.discoveryengine_v1alpha.ConversationalSearchServiceAsyncClient.update_session", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService.UpdateDataStore", + "fullName": "google.cloud.discoveryengine.v1alpha.ConversationalSearchService.UpdateSession", "service": { - "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService", - "shortName": "DataStoreService" + "fullName": "google.cloud.discoveryengine.v1alpha.ConversationalSearchService", + "shortName": "ConversationalSearchService" }, - "shortName": "UpdateDataStore" + "shortName": "UpdateSession" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.UpdateDataStoreRequest" + "type": "google.cloud.discoveryengine_v1alpha.types.UpdateSessionRequest" }, { - "name": "data_store", - "type": "google.cloud.discoveryengine_v1alpha.types.DataStore" + "name": "session", + "type": "google.cloud.discoveryengine_v1alpha.types.Session" }, { "name": "update_mask", @@ -2954,22 +3093,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1alpha.types.DataStore", - "shortName": "update_data_store" + "resultType": "google.cloud.discoveryengine_v1alpha.types.Session", + "shortName": "update_session" }, - "description": "Sample for UpdateDataStore", - "file": "discoveryengine_v1alpha_generated_data_store_service_update_data_store_async.py", + "description": "Sample for UpdateSession", + "file": "discoveryengine_v1alpha_generated_conversational_search_service_update_session_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_DataStoreService_UpdateDataStore_async", + "regionTag": "discoveryengine_v1alpha_generated_ConversationalSearchService_UpdateSession_async", "segments": [ { - "end": 54, + "end": 50, "start": 27, "type": "FULL" }, { - "end": 54, + "end": 50, "start": 27, "type": "SHORT" }, @@ -2979,47 +3118,47 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 48, + "end": 44, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 51, - "start": 49, + "end": 47, + "start": 45, "type": "REQUEST_EXECUTION" }, { - "end": 55, - "start": 52, + "end": 51, + "start": 48, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_data_store_service_update_data_store_async.py" + "title": "discoveryengine_v1alpha_generated_conversational_search_service_update_session_async.py" }, { "canonical": true, "clientMethod": { "client": { - "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceClient", - "shortName": "DataStoreServiceClient" + "fullName": "google.cloud.discoveryengine_v1alpha.ConversationalSearchServiceClient", + "shortName": "ConversationalSearchServiceClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceClient.update_data_store", + "fullName": "google.cloud.discoveryengine_v1alpha.ConversationalSearchServiceClient.update_session", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService.UpdateDataStore", + "fullName": "google.cloud.discoveryengine.v1alpha.ConversationalSearchService.UpdateSession", "service": { - "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService", - "shortName": "DataStoreService" + "fullName": "google.cloud.discoveryengine.v1alpha.ConversationalSearchService", + "shortName": "ConversationalSearchService" }, - "shortName": "UpdateDataStore" + "shortName": "UpdateSession" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.UpdateDataStoreRequest" + "type": "google.cloud.discoveryengine_v1alpha.types.UpdateSessionRequest" }, { - "name": "data_store", - "type": "google.cloud.discoveryengine_v1alpha.types.DataStore" + "name": "session", + "type": "google.cloud.discoveryengine_v1alpha.types.Session" }, { "name": "update_mask", @@ -3038,22 +3177,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1alpha.types.DataStore", - "shortName": "update_data_store" + "resultType": "google.cloud.discoveryengine_v1alpha.types.Session", + "shortName": "update_session" }, - "description": "Sample for UpdateDataStore", - "file": "discoveryengine_v1alpha_generated_data_store_service_update_data_store_sync.py", + "description": "Sample for UpdateSession", + "file": "discoveryengine_v1alpha_generated_conversational_search_service_update_session_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_DataStoreService_UpdateDataStore_sync", + "regionTag": "discoveryengine_v1alpha_generated_ConversationalSearchService_UpdateSession_sync", "segments": [ { - "end": 54, + "end": 50, "start": 27, "type": "FULL" }, { - "end": 54, + "end": 50, "start": 27, "type": "SHORT" }, @@ -3063,22 +3202,22 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 48, + "end": 44, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 51, - "start": 49, + "end": 47, + "start": 45, "type": "REQUEST_EXECUTION" }, { - "end": 55, - "start": 52, + "end": 51, + "start": 48, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_data_store_service_update_data_store_sync.py" + "title": "discoveryengine_v1alpha_generated_conversational_search_service_update_session_sync.py" }, { "canonical": true, @@ -3088,27 +3227,31 @@ "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceAsyncClient", "shortName": "DataStoreServiceAsyncClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceAsyncClient.update_document_processing_config", + "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceAsyncClient.create_data_store", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService.UpdateDocumentProcessingConfig", + "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService.CreateDataStore", "service": { "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService", "shortName": "DataStoreService" }, - "shortName": "UpdateDocumentProcessingConfig" + "shortName": "CreateDataStore" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.UpdateDocumentProcessingConfigRequest" + "type": "google.cloud.discoveryengine_v1alpha.types.CreateDataStoreRequest" }, { - "name": "document_processing_config", - "type": "google.cloud.discoveryengine_v1alpha.types.DocumentProcessingConfig" + "name": "parent", + "type": "str" }, { - "name": "update_mask", - "type": "google.protobuf.field_mask_pb2.FieldMask" + "name": "data_store", + "type": "google.cloud.discoveryengine_v1alpha.types.DataStore" + }, + { + "name": "data_store_id", + "type": "str" }, { "name": "retry", @@ -3123,22 +3266,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1alpha.types.DocumentProcessingConfig", - "shortName": "update_document_processing_config" + "resultType": "google.api_core.operation_async.AsyncOperation", + "shortName": "create_data_store" }, - "description": "Sample for UpdateDocumentProcessingConfig", - "file": "discoveryengine_v1alpha_generated_data_store_service_update_document_processing_config_async.py", + "description": "Sample for CreateDataStore", + "file": "discoveryengine_v1alpha_generated_data_store_service_create_data_store_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_DataStoreService_UpdateDocumentProcessingConfig_async", + "regionTag": "discoveryengine_v1alpha_generated_DataStoreService_CreateDataStore_async", "segments": [ { - "end": 50, + "end": 60, "start": 27, "type": "FULL" }, { - "end": 50, + "end": 60, "start": 27, "type": "SHORT" }, @@ -3148,22 +3291,22 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 44, + "end": 50, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 47, - "start": 45, + "end": 57, + "start": 51, "type": "REQUEST_EXECUTION" }, { - "end": 51, - "start": 48, + "end": 61, + "start": 58, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_data_store_service_update_document_processing_config_async.py" + "title": "discoveryengine_v1alpha_generated_data_store_service_create_data_store_async.py" }, { "canonical": true, @@ -3172,27 +3315,31 @@ "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceClient", "shortName": "DataStoreServiceClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceClient.update_document_processing_config", + "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceClient.create_data_store", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService.UpdateDocumentProcessingConfig", + "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService.CreateDataStore", "service": { "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService", "shortName": "DataStoreService" }, - "shortName": "UpdateDocumentProcessingConfig" + "shortName": "CreateDataStore" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.UpdateDocumentProcessingConfigRequest" + "type": "google.cloud.discoveryengine_v1alpha.types.CreateDataStoreRequest" }, { - "name": "document_processing_config", - "type": "google.cloud.discoveryengine_v1alpha.types.DocumentProcessingConfig" + "name": "parent", + "type": "str" }, { - "name": "update_mask", - "type": "google.protobuf.field_mask_pb2.FieldMask" + "name": "data_store", + "type": "google.cloud.discoveryengine_v1alpha.types.DataStore" + }, + { + "name": "data_store_id", + "type": "str" }, { "name": "retry", @@ -3207,22 +3354,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1alpha.types.DocumentProcessingConfig", - "shortName": "update_document_processing_config" + "resultType": "google.api_core.operation.Operation", + "shortName": "create_data_store" }, - "description": "Sample for UpdateDocumentProcessingConfig", - "file": "discoveryengine_v1alpha_generated_data_store_service_update_document_processing_config_sync.py", + "description": "Sample for CreateDataStore", + "file": "discoveryengine_v1alpha_generated_data_store_service_create_data_store_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_DataStoreService_UpdateDocumentProcessingConfig_sync", + "regionTag": "discoveryengine_v1alpha_generated_DataStoreService_CreateDataStore_sync", "segments": [ { - "end": 50, + "end": 60, "start": 27, "type": "FULL" }, { - "end": 50, + "end": 60, "start": 27, "type": "SHORT" }, @@ -3232,55 +3379,47 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 44, + "end": 50, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 47, - "start": 45, + "end": 57, + "start": 51, "type": "REQUEST_EXECUTION" }, { - "end": 51, - "start": 48, + "end": 61, + "start": 58, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_data_store_service_update_document_processing_config_sync.py" + "title": "discoveryengine_v1alpha_generated_data_store_service_create_data_store_sync.py" }, { "canonical": true, "clientMethod": { "async": true, "client": { - "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceAsyncClient", - "shortName": "DocumentServiceAsyncClient" + "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceAsyncClient", + "shortName": "DataStoreServiceAsyncClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceAsyncClient.create_document", + "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceAsyncClient.delete_data_store", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService.CreateDocument", + "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService.DeleteDataStore", "service": { - "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService", - "shortName": "DocumentService" + "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService", + "shortName": "DataStoreService" }, - "shortName": "CreateDocument" + "shortName": "DeleteDataStore" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.CreateDocumentRequest" - }, - { - "name": "parent", - "type": "str" - }, - { - "name": "document", - "type": "google.cloud.discoveryengine_v1alpha.types.Document" + "type": "google.cloud.discoveryengine_v1alpha.types.DeleteDataStoreRequest" }, { - "name": "document_id", + "name": "name", "type": "str" }, { @@ -3296,22 +3435,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1alpha.types.Document", - "shortName": "create_document" + "resultType": "google.api_core.operation_async.AsyncOperation", + "shortName": "delete_data_store" }, - "description": "Sample for CreateDocument", - "file": "discoveryengine_v1alpha_generated_document_service_create_document_async.py", + "description": "Sample for DeleteDataStore", + "file": "discoveryengine_v1alpha_generated_data_store_service_delete_data_store_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_DocumentService_CreateDocument_async", + "regionTag": "discoveryengine_v1alpha_generated_DataStoreService_DeleteDataStore_async", "segments": [ { - "end": 52, + "end": 55, "start": 27, "type": "FULL" }, { - "end": 52, + "end": 55, "start": 27, "type": "SHORT" }, @@ -3321,54 +3460,46 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 46, + "end": 45, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 49, - "start": 47, + "end": 52, + "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 53, - "start": 50, + "end": 56, + "start": 53, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_document_service_create_document_async.py" + "title": "discoveryengine_v1alpha_generated_data_store_service_delete_data_store_async.py" }, { "canonical": true, "clientMethod": { "client": { - "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceClient", - "shortName": "DocumentServiceClient" + "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceClient", + "shortName": "DataStoreServiceClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceClient.create_document", + "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceClient.delete_data_store", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService.CreateDocument", + "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService.DeleteDataStore", "service": { - "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService", - "shortName": "DocumentService" + "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService", + "shortName": "DataStoreService" }, - "shortName": "CreateDocument" + "shortName": "DeleteDataStore" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.CreateDocumentRequest" - }, - { - "name": "parent", - "type": "str" - }, - { - "name": "document", - "type": "google.cloud.discoveryengine_v1alpha.types.Document" + "type": "google.cloud.discoveryengine_v1alpha.types.DeleteDataStoreRequest" }, { - "name": "document_id", + "name": "name", "type": "str" }, { @@ -3384,22 +3515,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1alpha.types.Document", - "shortName": "create_document" + "resultType": "google.api_core.operation.Operation", + "shortName": "delete_data_store" }, - "description": "Sample for CreateDocument", - "file": "discoveryengine_v1alpha_generated_document_service_create_document_sync.py", + "description": "Sample for DeleteDataStore", + "file": "discoveryengine_v1alpha_generated_data_store_service_delete_data_store_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_DocumentService_CreateDocument_sync", + "regionTag": "discoveryengine_v1alpha_generated_DataStoreService_DeleteDataStore_sync", "segments": [ { - "end": 52, + "end": 55, "start": 27, "type": "FULL" }, { - "end": 52, + "end": 55, "start": 27, "type": "SHORT" }, @@ -3409,44 +3540,44 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 46, + "end": 45, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 49, - "start": 47, + "end": 52, + "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 53, - "start": 50, + "end": 56, + "start": 53, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_document_service_create_document_sync.py" + "title": "discoveryengine_v1alpha_generated_data_store_service_delete_data_store_sync.py" }, { "canonical": true, "clientMethod": { "async": true, "client": { - "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceAsyncClient", - "shortName": "DocumentServiceAsyncClient" + "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceAsyncClient", + "shortName": "DataStoreServiceAsyncClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceAsyncClient.delete_document", + "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceAsyncClient.get_data_store", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService.DeleteDocument", + "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService.GetDataStore", "service": { - "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService", - "shortName": "DocumentService" + "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService", + "shortName": "DataStoreService" }, - "shortName": "DeleteDocument" + "shortName": "GetDataStore" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.DeleteDocumentRequest" + "type": "google.cloud.discoveryengine_v1alpha.types.GetDataStoreRequest" }, { "name": "name", @@ -3465,21 +3596,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "shortName": "delete_document" + "resultType": "google.cloud.discoveryengine_v1alpha.types.DataStore", + "shortName": "get_data_store" }, - "description": "Sample for DeleteDocument", - "file": "discoveryengine_v1alpha_generated_document_service_delete_document_async.py", + "description": "Sample for GetDataStore", + "file": "discoveryengine_v1alpha_generated_data_store_service_get_data_store_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_DocumentService_DeleteDocument_async", + "regionTag": "discoveryengine_v1alpha_generated_DataStoreService_GetDataStore_async", "segments": [ { - "end": 49, + "end": 51, "start": 27, "type": "FULL" }, { - "end": 49, + "end": 51, "start": 27, "type": "SHORT" }, @@ -3494,36 +3626,38 @@ "type": "REQUEST_INITIALIZATION" }, { + "end": 48, "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 50, + "end": 52, + "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_document_service_delete_document_async.py" + "title": "discoveryengine_v1alpha_generated_data_store_service_get_data_store_async.py" }, { "canonical": true, "clientMethod": { "client": { - "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceClient", - "shortName": "DocumentServiceClient" + "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceClient", + "shortName": "DataStoreServiceClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceClient.delete_document", + "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceClient.get_data_store", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService.DeleteDocument", + "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService.GetDataStore", "service": { - "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService", - "shortName": "DocumentService" + "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService", + "shortName": "DataStoreService" }, - "shortName": "DeleteDocument" + "shortName": "GetDataStore" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.DeleteDocumentRequest" + "type": "google.cloud.discoveryengine_v1alpha.types.GetDataStoreRequest" }, { "name": "name", @@ -3542,21 +3676,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "shortName": "delete_document" + "resultType": "google.cloud.discoveryengine_v1alpha.types.DataStore", + "shortName": "get_data_store" }, - "description": "Sample for DeleteDocument", - "file": "discoveryengine_v1alpha_generated_document_service_delete_document_sync.py", + "description": "Sample for GetDataStore", + "file": "discoveryengine_v1alpha_generated_data_store_service_get_data_store_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_DocumentService_DeleteDocument_sync", + "regionTag": "discoveryengine_v1alpha_generated_DataStoreService_GetDataStore_sync", "segments": [ { - "end": 49, + "end": 51, "start": 27, "type": "FULL" }, { - "end": 49, + "end": 51, "start": 27, "type": "SHORT" }, @@ -3571,37 +3706,39 @@ "type": "REQUEST_INITIALIZATION" }, { + "end": 48, "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 50, + "end": 52, + "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_document_service_delete_document_sync.py" + "title": "discoveryengine_v1alpha_generated_data_store_service_get_data_store_sync.py" }, { "canonical": true, "clientMethod": { "async": true, "client": { - "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceAsyncClient", - "shortName": "DocumentServiceAsyncClient" + "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceAsyncClient", + "shortName": "DataStoreServiceAsyncClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceAsyncClient.get_document", + "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceAsyncClient.get_document_processing_config", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService.GetDocument", + "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService.GetDocumentProcessingConfig", "service": { - "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService", - "shortName": "DocumentService" + "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService", + "shortName": "DataStoreService" }, - "shortName": "GetDocument" + "shortName": "GetDocumentProcessingConfig" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.GetDocumentRequest" + "type": "google.cloud.discoveryengine_v1alpha.types.GetDocumentProcessingConfigRequest" }, { "name": "name", @@ -3620,14 +3757,14 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1alpha.types.Document", - "shortName": "get_document" + "resultType": "google.cloud.discoveryengine_v1alpha.types.DocumentProcessingConfig", + "shortName": "get_document_processing_config" }, - "description": "Sample for GetDocument", - "file": "discoveryengine_v1alpha_generated_document_service_get_document_async.py", + "description": "Sample for GetDocumentProcessingConfig", + "file": "discoveryengine_v1alpha_generated_data_store_service_get_document_processing_config_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_DocumentService_GetDocument_async", + "regionTag": "discoveryengine_v1alpha_generated_DataStoreService_GetDocumentProcessingConfig_async", "segments": [ { "end": 51, @@ -3660,28 +3797,28 @@ "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_document_service_get_document_async.py" + "title": "discoveryengine_v1alpha_generated_data_store_service_get_document_processing_config_async.py" }, { "canonical": true, "clientMethod": { "client": { - "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceClient", - "shortName": "DocumentServiceClient" + "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceClient", + "shortName": "DataStoreServiceClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceClient.get_document", + "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceClient.get_document_processing_config", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService.GetDocument", + "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService.GetDocumentProcessingConfig", "service": { - "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService", - "shortName": "DocumentService" + "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService", + "shortName": "DataStoreService" }, - "shortName": "GetDocument" + "shortName": "GetDocumentProcessingConfig" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.GetDocumentRequest" + "type": "google.cloud.discoveryengine_v1alpha.types.GetDocumentProcessingConfigRequest" }, { "name": "name", @@ -3700,14 +3837,14 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1alpha.types.Document", - "shortName": "get_document" + "resultType": "google.cloud.discoveryengine_v1alpha.types.DocumentProcessingConfig", + "shortName": "get_document_processing_config" }, - "description": "Sample for GetDocument", - "file": "discoveryengine_v1alpha_generated_document_service_get_document_sync.py", + "description": "Sample for GetDocumentProcessingConfig", + "file": "discoveryengine_v1alpha_generated_data_store_service_get_document_processing_config_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_DocumentService_GetDocument_sync", + "regionTag": "discoveryengine_v1alpha_generated_DataStoreService_GetDocumentProcessingConfig_sync", "segments": [ { "end": 51, @@ -3740,29 +3877,33 @@ "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_document_service_get_document_sync.py" + "title": "discoveryengine_v1alpha_generated_data_store_service_get_document_processing_config_sync.py" }, { "canonical": true, "clientMethod": { "async": true, "client": { - "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceAsyncClient", - "shortName": "DocumentServiceAsyncClient" + "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceAsyncClient", + "shortName": "DataStoreServiceAsyncClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceAsyncClient.import_documents", + "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceAsyncClient.list_data_stores", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService.ImportDocuments", + "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService.ListDataStores", "service": { - "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService", - "shortName": "DocumentService" + "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService", + "shortName": "DataStoreService" }, - "shortName": "ImportDocuments" + "shortName": "ListDataStores" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.ImportDocumentsRequest" + "type": "google.cloud.discoveryengine_v1alpha.types.ListDataStoresRequest" + }, + { + "name": "parent", + "type": "str" }, { "name": "retry", @@ -3777,22 +3918,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.api_core.operation_async.AsyncOperation", - "shortName": "import_documents" + "resultType": "google.cloud.discoveryengine_v1alpha.services.data_store_service.pagers.ListDataStoresAsyncPager", + "shortName": "list_data_stores" }, - "description": "Sample for ImportDocuments", - "file": "discoveryengine_v1alpha_generated_document_service_import_documents_async.py", + "description": "Sample for ListDataStores", + "file": "discoveryengine_v1alpha_generated_data_store_service_list_data_stores_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_DocumentService_ImportDocuments_async", + "regionTag": "discoveryengine_v1alpha_generated_DataStoreService_ListDataStores_async", "segments": [ { - "end": 55, + "end": 52, "start": 27, "type": "FULL" }, { - "end": 55, + "end": 52, "start": 27, "type": "SHORT" }, @@ -3807,38 +3948,42 @@ "type": "REQUEST_INITIALIZATION" }, { - "end": 52, + "end": 48, "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 56, - "start": 53, + "end": 53, + "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_document_service_import_documents_async.py" + "title": "discoveryengine_v1alpha_generated_data_store_service_list_data_stores_async.py" }, { "canonical": true, "clientMethod": { "client": { - "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceClient", - "shortName": "DocumentServiceClient" + "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceClient", + "shortName": "DataStoreServiceClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceClient.import_documents", + "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceClient.list_data_stores", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService.ImportDocuments", + "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService.ListDataStores", "service": { - "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService", - "shortName": "DocumentService" + "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService", + "shortName": "DataStoreService" }, - "shortName": "ImportDocuments" + "shortName": "ListDataStores" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.ImportDocumentsRequest" + "type": "google.cloud.discoveryengine_v1alpha.types.ListDataStoresRequest" + }, + { + "name": "parent", + "type": "str" }, { "name": "retry", @@ -3853,22 +3998,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.api_core.operation.Operation", - "shortName": "import_documents" + "resultType": "google.cloud.discoveryengine_v1alpha.services.data_store_service.pagers.ListDataStoresPager", + "shortName": "list_data_stores" }, - "description": "Sample for ImportDocuments", - "file": "discoveryengine_v1alpha_generated_document_service_import_documents_sync.py", + "description": "Sample for ListDataStores", + "file": "discoveryengine_v1alpha_generated_data_store_service_list_data_stores_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_DocumentService_ImportDocuments_sync", + "regionTag": "discoveryengine_v1alpha_generated_DataStoreService_ListDataStores_sync", "segments": [ { - "end": 55, + "end": 52, "start": 27, "type": "FULL" }, { - "end": 55, + "end": 52, "start": 27, "type": "SHORT" }, @@ -3883,43 +4028,47 @@ "type": "REQUEST_INITIALIZATION" }, { - "end": 52, + "end": 48, "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 56, - "start": 53, + "end": 53, + "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_document_service_import_documents_sync.py" + "title": "discoveryengine_v1alpha_generated_data_store_service_list_data_stores_sync.py" }, { "canonical": true, "clientMethod": { "async": true, "client": { - "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceAsyncClient", - "shortName": "DocumentServiceAsyncClient" + "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceAsyncClient", + "shortName": "DataStoreServiceAsyncClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceAsyncClient.list_documents", + "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceAsyncClient.update_data_store", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService.ListDocuments", + "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService.UpdateDataStore", "service": { - "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService", - "shortName": "DocumentService" + "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService", + "shortName": "DataStoreService" }, - "shortName": "ListDocuments" + "shortName": "UpdateDataStore" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.ListDocumentsRequest" + "type": "google.cloud.discoveryengine_v1alpha.types.UpdateDataStoreRequest" }, { - "name": "parent", - "type": "str" + "name": "data_store", + "type": "google.cloud.discoveryengine_v1alpha.types.DataStore" + }, + { + "name": "update_mask", + "type": "google.protobuf.field_mask_pb2.FieldMask" }, { "name": "retry", @@ -3934,22 +4083,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1alpha.services.document_service.pagers.ListDocumentsAsyncPager", - "shortName": "list_documents" + "resultType": "google.cloud.discoveryengine_v1alpha.types.DataStore", + "shortName": "update_data_store" }, - "description": "Sample for ListDocuments", - "file": "discoveryengine_v1alpha_generated_document_service_list_documents_async.py", + "description": "Sample for UpdateDataStore", + "file": "discoveryengine_v1alpha_generated_data_store_service_update_data_store_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_DocumentService_ListDocuments_async", + "regionTag": "discoveryengine_v1alpha_generated_DataStoreService_UpdateDataStore_async", "segments": [ { - "end": 52, + "end": 54, "start": 27, "type": "FULL" }, { - "end": 52, + "end": 54, "start": 27, "type": "SHORT" }, @@ -3959,47 +4108,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": 53, - "start": 49, + "end": 55, + "start": 52, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_document_service_list_documents_async.py" + "title": "discoveryengine_v1alpha_generated_data_store_service_update_data_store_async.py" }, { "canonical": true, "clientMethod": { "client": { - "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceClient", - "shortName": "DocumentServiceClient" + "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceClient", + "shortName": "DataStoreServiceClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceClient.list_documents", + "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceClient.update_data_store", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService.ListDocuments", + "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService.UpdateDataStore", "service": { - "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService", - "shortName": "DocumentService" + "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService", + "shortName": "DataStoreService" }, - "shortName": "ListDocuments" + "shortName": "UpdateDataStore" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.ListDocumentsRequest" + "type": "google.cloud.discoveryengine_v1alpha.types.UpdateDataStoreRequest" }, { - "name": "parent", - "type": "str" + "name": "data_store", + "type": "google.cloud.discoveryengine_v1alpha.types.DataStore" + }, + { + "name": "update_mask", + "type": "google.protobuf.field_mask_pb2.FieldMask" }, { "name": "retry", @@ -4014,22 +4167,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1alpha.services.document_service.pagers.ListDocumentsPager", - "shortName": "list_documents" + "resultType": "google.cloud.discoveryengine_v1alpha.types.DataStore", + "shortName": "update_data_store" }, - "description": "Sample for ListDocuments", - "file": "discoveryengine_v1alpha_generated_document_service_list_documents_sync.py", + "description": "Sample for UpdateDataStore", + "file": "discoveryengine_v1alpha_generated_data_store_service_update_data_store_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_DocumentService_ListDocuments_sync", + "regionTag": "discoveryengine_v1alpha_generated_DataStoreService_UpdateDataStore_sync", "segments": [ { - "end": 52, + "end": 54, "start": 27, "type": "FULL" }, { - "end": 52, + "end": 54, "start": 27, "type": "SHORT" }, @@ -4039,44 +4192,52 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 45, + "end": 48, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 48, - "start": 46, + "end": 51, + "start": 49, "type": "REQUEST_EXECUTION" }, { - "end": 53, - "start": 49, + "end": 55, + "start": 52, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_document_service_list_documents_sync.py" + "title": "discoveryengine_v1alpha_generated_data_store_service_update_data_store_sync.py" }, { "canonical": true, "clientMethod": { "async": true, "client": { - "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceAsyncClient", - "shortName": "DocumentServiceAsyncClient" + "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceAsyncClient", + "shortName": "DataStoreServiceAsyncClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceAsyncClient.purge_documents", + "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceAsyncClient.update_document_processing_config", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService.PurgeDocuments", + "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService.UpdateDocumentProcessingConfig", "service": { - "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService", - "shortName": "DocumentService" + "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService", + "shortName": "DataStoreService" }, - "shortName": "PurgeDocuments" + "shortName": "UpdateDocumentProcessingConfig" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.PurgeDocumentsRequest" + "type": "google.cloud.discoveryengine_v1alpha.types.UpdateDocumentProcessingConfigRequest" + }, + { + "name": "document_processing_config", + "type": "google.cloud.discoveryengine_v1alpha.types.DocumentProcessingConfig" + }, + { + "name": "update_mask", + "type": "google.protobuf.field_mask_pb2.FieldMask" }, { "name": "retry", @@ -4091,22 +4252,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.api_core.operation_async.AsyncOperation", - "shortName": "purge_documents" + "resultType": "google.cloud.discoveryengine_v1alpha.types.DocumentProcessingConfig", + "shortName": "update_document_processing_config" }, - "description": "Sample for PurgeDocuments", - "file": "discoveryengine_v1alpha_generated_document_service_purge_documents_async.py", + "description": "Sample for UpdateDocumentProcessingConfig", + "file": "discoveryengine_v1alpha_generated_data_store_service_update_document_processing_config_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_DocumentService_PurgeDocuments_async", + "regionTag": "discoveryengine_v1alpha_generated_DataStoreService_UpdateDocumentProcessingConfig_async", "segments": [ { - "end": 60, + "end": 50, "start": 27, "type": "FULL" }, { - "end": 60, + "end": 50, "start": 27, "type": "SHORT" }, @@ -4116,43 +4277,51 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 50, + "end": 44, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 57, - "start": 51, + "end": 47, + "start": 45, "type": "REQUEST_EXECUTION" }, { - "end": 61, - "start": 58, + "end": 51, + "start": 48, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_document_service_purge_documents_async.py" + "title": "discoveryengine_v1alpha_generated_data_store_service_update_document_processing_config_async.py" }, { "canonical": true, "clientMethod": { "client": { - "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceClient", - "shortName": "DocumentServiceClient" + "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceClient", + "shortName": "DataStoreServiceClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceClient.purge_documents", + "fullName": "google.cloud.discoveryengine_v1alpha.DataStoreServiceClient.update_document_processing_config", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService.PurgeDocuments", + "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService.UpdateDocumentProcessingConfig", "service": { - "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService", - "shortName": "DocumentService" + "fullName": "google.cloud.discoveryengine.v1alpha.DataStoreService", + "shortName": "DataStoreService" }, - "shortName": "PurgeDocuments" + "shortName": "UpdateDocumentProcessingConfig" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.PurgeDocumentsRequest" + "type": "google.cloud.discoveryengine_v1alpha.types.UpdateDocumentProcessingConfigRequest" + }, + { + "name": "document_processing_config", + "type": "google.cloud.discoveryengine_v1alpha.types.DocumentProcessingConfig" + }, + { + "name": "update_mask", + "type": "google.protobuf.field_mask_pb2.FieldMask" }, { "name": "retry", @@ -4167,22 +4336,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.api_core.operation.Operation", - "shortName": "purge_documents" + "resultType": "google.cloud.discoveryengine_v1alpha.types.DocumentProcessingConfig", + "shortName": "update_document_processing_config" }, - "description": "Sample for PurgeDocuments", - "file": "discoveryengine_v1alpha_generated_document_service_purge_documents_sync.py", + "description": "Sample for UpdateDocumentProcessingConfig", + "file": "discoveryengine_v1alpha_generated_data_store_service_update_document_processing_config_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_DocumentService_PurgeDocuments_sync", + "regionTag": "discoveryengine_v1alpha_generated_DataStoreService_UpdateDocumentProcessingConfig_sync", "segments": [ { - "end": 60, + "end": 50, "start": 27, "type": "FULL" }, { - "end": 60, + "end": 50, "start": 27, "type": "SHORT" }, @@ -4192,22 +4361,22 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 50, + "end": 44, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 57, - "start": 51, + "end": 47, + "start": 45, "type": "REQUEST_EXECUTION" }, { - "end": 61, - "start": 58, + "end": 51, + "start": 48, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_document_service_purge_documents_sync.py" + "title": "discoveryengine_v1alpha_generated_data_store_service_update_document_processing_config_sync.py" }, { "canonical": true, @@ -4217,27 +4386,31 @@ "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceAsyncClient", "shortName": "DocumentServiceAsyncClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceAsyncClient.update_document", + "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceAsyncClient.create_document", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService.UpdateDocument", + "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService.CreateDocument", "service": { "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService", "shortName": "DocumentService" }, - "shortName": "UpdateDocument" + "shortName": "CreateDocument" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.UpdateDocumentRequest" + "type": "google.cloud.discoveryengine_v1alpha.types.CreateDocumentRequest" + }, + { + "name": "parent", + "type": "str" }, { "name": "document", "type": "google.cloud.discoveryengine_v1alpha.types.Document" }, { - "name": "update_mask", - "type": "google.protobuf.field_mask_pb2.FieldMask" + "name": "document_id", + "type": "str" }, { "name": "retry", @@ -4253,21 +4426,21 @@ } ], "resultType": "google.cloud.discoveryengine_v1alpha.types.Document", - "shortName": "update_document" + "shortName": "create_document" }, - "description": "Sample for UpdateDocument", - "file": "discoveryengine_v1alpha_generated_document_service_update_document_async.py", + "description": "Sample for CreateDocument", + "file": "discoveryengine_v1alpha_generated_document_service_create_document_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_DocumentService_UpdateDocument_async", + "regionTag": "discoveryengine_v1alpha_generated_DocumentService_CreateDocument_async", "segments": [ { - "end": 50, + "end": 52, "start": 27, "type": "FULL" }, { - "end": 50, + "end": 52, "start": 27, "type": "SHORT" }, @@ -4277,22 +4450,22 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 44, + "end": 46, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 47, - "start": 45, + "end": 49, + "start": 47, "type": "REQUEST_EXECUTION" }, { - "end": 51, - "start": 48, + "end": 53, + "start": 50, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_document_service_update_document_async.py" + "title": "discoveryengine_v1alpha_generated_document_service_create_document_async.py" }, { "canonical": true, @@ -4301,27 +4474,31 @@ "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceClient", "shortName": "DocumentServiceClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceClient.update_document", + "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceClient.create_document", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService.UpdateDocument", + "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService.CreateDocument", "service": { "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService", "shortName": "DocumentService" }, - "shortName": "UpdateDocument" + "shortName": "CreateDocument" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.UpdateDocumentRequest" + "type": "google.cloud.discoveryengine_v1alpha.types.CreateDocumentRequest" + }, + { + "name": "parent", + "type": "str" }, { "name": "document", "type": "google.cloud.discoveryengine_v1alpha.types.Document" }, { - "name": "update_mask", - "type": "google.protobuf.field_mask_pb2.FieldMask" + "name": "document_id", + "type": "str" }, { "name": "retry", @@ -4337,21 +4514,21 @@ } ], "resultType": "google.cloud.discoveryengine_v1alpha.types.Document", - "shortName": "update_document" + "shortName": "create_document" }, - "description": "Sample for UpdateDocument", - "file": "discoveryengine_v1alpha_generated_document_service_update_document_sync.py", + "description": "Sample for CreateDocument", + "file": "discoveryengine_v1alpha_generated_document_service_create_document_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_DocumentService_UpdateDocument_sync", + "regionTag": "discoveryengine_v1alpha_generated_DocumentService_CreateDocument_sync", "segments": [ { - "end": 50, + "end": 52, "start": 27, "type": "FULL" }, { - "end": 50, + "end": 52, "start": 27, "type": "SHORT" }, @@ -4361,55 +4538,1981 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 44, + "end": 46, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 47, - "start": 45, + "end": 49, + "start": 47, "type": "REQUEST_EXECUTION" }, { - "end": 51, - "start": 48, + "end": 53, + "start": 50, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_document_service_update_document_sync.py" + "title": "discoveryengine_v1alpha_generated_document_service_create_document_sync.py" }, { "canonical": true, "clientMethod": { "async": true, "client": { - "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceAsyncClient", - "shortName": "EngineServiceAsyncClient" + "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceAsyncClient", + "shortName": "DocumentServiceAsyncClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceAsyncClient.create_engine", + "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceAsyncClient.delete_document", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.EngineService.CreateEngine", + "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService.DeleteDocument", "service": { - "fullName": "google.cloud.discoveryengine.v1alpha.EngineService", - "shortName": "EngineService" + "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService", + "shortName": "DocumentService" }, - "shortName": "CreateEngine" + "shortName": "DeleteDocument" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.CreateEngineRequest" + "type": "google.cloud.discoveryengine_v1alpha.types.DeleteDocumentRequest" }, { - "name": "parent", + "name": "name", "type": "str" }, { - "name": "engine", - "type": "google.cloud.discoveryengine_v1alpha.types.Engine" + "name": "retry", + "type": "google.api_core.retry.Retry" }, { - "name": "engine_id", + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "shortName": "delete_document" + }, + "description": "Sample for DeleteDocument", + "file": "discoveryengine_v1alpha_generated_document_service_delete_document_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "discoveryengine_v1alpha_generated_DocumentService_DeleteDocument_async", + "segments": [ + { + "end": 49, + "start": 27, + "type": "FULL" + }, + { + "end": 49, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 45, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "start": 46, + "type": "REQUEST_EXECUTION" + }, + { + "end": 50, + "type": "RESPONSE_HANDLING" + } + ], + "title": "discoveryengine_v1alpha_generated_document_service_delete_document_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceClient", + "shortName": "DocumentServiceClient" + }, + "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceClient.delete_document", + "method": { + "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService.DeleteDocument", + "service": { + "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService", + "shortName": "DocumentService" + }, + "shortName": "DeleteDocument" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.discoveryengine_v1alpha.types.DeleteDocumentRequest" + }, + { + "name": "name", + "type": "str" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "shortName": "delete_document" + }, + "description": "Sample for DeleteDocument", + "file": "discoveryengine_v1alpha_generated_document_service_delete_document_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "discoveryengine_v1alpha_generated_DocumentService_DeleteDocument_sync", + "segments": [ + { + "end": 49, + "start": 27, + "type": "FULL" + }, + { + "end": 49, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 45, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "start": 46, + "type": "REQUEST_EXECUTION" + }, + { + "end": 50, + "type": "RESPONSE_HANDLING" + } + ], + "title": "discoveryengine_v1alpha_generated_document_service_delete_document_sync.py" + }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceAsyncClient", + "shortName": "DocumentServiceAsyncClient" + }, + "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceAsyncClient.get_document", + "method": { + "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService.GetDocument", + "service": { + "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService", + "shortName": "DocumentService" + }, + "shortName": "GetDocument" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.discoveryengine_v1alpha.types.GetDocumentRequest" + }, + { + "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.discoveryengine_v1alpha.types.Document", + "shortName": "get_document" + }, + "description": "Sample for GetDocument", + "file": "discoveryengine_v1alpha_generated_document_service_get_document_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "discoveryengine_v1alpha_generated_DocumentService_GetDocument_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": "discoveryengine_v1alpha_generated_document_service_get_document_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceClient", + "shortName": "DocumentServiceClient" + }, + "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceClient.get_document", + "method": { + "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService.GetDocument", + "service": { + "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService", + "shortName": "DocumentService" + }, + "shortName": "GetDocument" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.discoveryengine_v1alpha.types.GetDocumentRequest" + }, + { + "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.discoveryengine_v1alpha.types.Document", + "shortName": "get_document" + }, + "description": "Sample for GetDocument", + "file": "discoveryengine_v1alpha_generated_document_service_get_document_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "discoveryengine_v1alpha_generated_DocumentService_GetDocument_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": "discoveryengine_v1alpha_generated_document_service_get_document_sync.py" + }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceAsyncClient", + "shortName": "DocumentServiceAsyncClient" + }, + "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceAsyncClient.get_processed_document", + "method": { + "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService.GetProcessedDocument", + "service": { + "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService", + "shortName": "DocumentService" + }, + "shortName": "GetProcessedDocument" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.discoveryengine_v1alpha.types.GetProcessedDocumentRequest" + }, + { + "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.discoveryengine_v1alpha.types.ProcessedDocument", + "shortName": "get_processed_document" + }, + "description": "Sample for GetProcessedDocument", + "file": "discoveryengine_v1alpha_generated_document_service_get_processed_document_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "discoveryengine_v1alpha_generated_DocumentService_GetProcessedDocument_async", + "segments": [ + { + "end": 52, + "start": 27, + "type": "FULL" + }, + { + "end": 52, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 46, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 49, + "start": 47, + "type": "REQUEST_EXECUTION" + }, + { + "end": 53, + "start": 50, + "type": "RESPONSE_HANDLING" + } + ], + "title": "discoveryengine_v1alpha_generated_document_service_get_processed_document_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceClient", + "shortName": "DocumentServiceClient" + }, + "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceClient.get_processed_document", + "method": { + "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService.GetProcessedDocument", + "service": { + "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService", + "shortName": "DocumentService" + }, + "shortName": "GetProcessedDocument" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.discoveryengine_v1alpha.types.GetProcessedDocumentRequest" + }, + { + "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.discoveryengine_v1alpha.types.ProcessedDocument", + "shortName": "get_processed_document" + }, + "description": "Sample for GetProcessedDocument", + "file": "discoveryengine_v1alpha_generated_document_service_get_processed_document_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "discoveryengine_v1alpha_generated_DocumentService_GetProcessedDocument_sync", + "segments": [ + { + "end": 52, + "start": 27, + "type": "FULL" + }, + { + "end": 52, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 46, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 49, + "start": 47, + "type": "REQUEST_EXECUTION" + }, + { + "end": 53, + "start": 50, + "type": "RESPONSE_HANDLING" + } + ], + "title": "discoveryengine_v1alpha_generated_document_service_get_processed_document_sync.py" + }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceAsyncClient", + "shortName": "DocumentServiceAsyncClient" + }, + "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceAsyncClient.import_documents", + "method": { + "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService.ImportDocuments", + "service": { + "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService", + "shortName": "DocumentService" + }, + "shortName": "ImportDocuments" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.discoveryengine_v1alpha.types.ImportDocumentsRequest" + }, + { + "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": "import_documents" + }, + "description": "Sample for ImportDocuments", + "file": "discoveryengine_v1alpha_generated_document_service_import_documents_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "discoveryengine_v1alpha_generated_DocumentService_ImportDocuments_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": "discoveryengine_v1alpha_generated_document_service_import_documents_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceClient", + "shortName": "DocumentServiceClient" + }, + "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceClient.import_documents", + "method": { + "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService.ImportDocuments", + "service": { + "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService", + "shortName": "DocumentService" + }, + "shortName": "ImportDocuments" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.discoveryengine_v1alpha.types.ImportDocumentsRequest" + }, + { + "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": "import_documents" + }, + "description": "Sample for ImportDocuments", + "file": "discoveryengine_v1alpha_generated_document_service_import_documents_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "discoveryengine_v1alpha_generated_DocumentService_ImportDocuments_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": "discoveryengine_v1alpha_generated_document_service_import_documents_sync.py" + }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceAsyncClient", + "shortName": "DocumentServiceAsyncClient" + }, + "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceAsyncClient.list_documents", + "method": { + "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService.ListDocuments", + "service": { + "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService", + "shortName": "DocumentService" + }, + "shortName": "ListDocuments" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.discoveryengine_v1alpha.types.ListDocumentsRequest" + }, + { + "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.discoveryengine_v1alpha.services.document_service.pagers.ListDocumentsAsyncPager", + "shortName": "list_documents" + }, + "description": "Sample for ListDocuments", + "file": "discoveryengine_v1alpha_generated_document_service_list_documents_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "discoveryengine_v1alpha_generated_DocumentService_ListDocuments_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": "discoveryengine_v1alpha_generated_document_service_list_documents_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceClient", + "shortName": "DocumentServiceClient" + }, + "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceClient.list_documents", + "method": { + "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService.ListDocuments", + "service": { + "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService", + "shortName": "DocumentService" + }, + "shortName": "ListDocuments" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.discoveryengine_v1alpha.types.ListDocumentsRequest" + }, + { + "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.discoveryengine_v1alpha.services.document_service.pagers.ListDocumentsPager", + "shortName": "list_documents" + }, + "description": "Sample for ListDocuments", + "file": "discoveryengine_v1alpha_generated_document_service_list_documents_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "discoveryengine_v1alpha_generated_DocumentService_ListDocuments_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": "discoveryengine_v1alpha_generated_document_service_list_documents_sync.py" + }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceAsyncClient", + "shortName": "DocumentServiceAsyncClient" + }, + "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceAsyncClient.purge_documents", + "method": { + "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService.PurgeDocuments", + "service": { + "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService", + "shortName": "DocumentService" + }, + "shortName": "PurgeDocuments" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.discoveryengine_v1alpha.types.PurgeDocumentsRequest" + }, + { + "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": "purge_documents" + }, + "description": "Sample for PurgeDocuments", + "file": "discoveryengine_v1alpha_generated_document_service_purge_documents_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "discoveryengine_v1alpha_generated_DocumentService_PurgeDocuments_async", + "segments": [ + { + "end": 60, + "start": 27, + "type": "FULL" + }, + { + "end": 60, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 50, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 57, + "start": 51, + "type": "REQUEST_EXECUTION" + }, + { + "end": 61, + "start": 58, + "type": "RESPONSE_HANDLING" + } + ], + "title": "discoveryengine_v1alpha_generated_document_service_purge_documents_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceClient", + "shortName": "DocumentServiceClient" + }, + "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceClient.purge_documents", + "method": { + "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService.PurgeDocuments", + "service": { + "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService", + "shortName": "DocumentService" + }, + "shortName": "PurgeDocuments" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.discoveryengine_v1alpha.types.PurgeDocumentsRequest" + }, + { + "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": "purge_documents" + }, + "description": "Sample for PurgeDocuments", + "file": "discoveryengine_v1alpha_generated_document_service_purge_documents_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "discoveryengine_v1alpha_generated_DocumentService_PurgeDocuments_sync", + "segments": [ + { + "end": 60, + "start": 27, + "type": "FULL" + }, + { + "end": 60, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 50, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 57, + "start": 51, + "type": "REQUEST_EXECUTION" + }, + { + "end": 61, + "start": 58, + "type": "RESPONSE_HANDLING" + } + ], + "title": "discoveryengine_v1alpha_generated_document_service_purge_documents_sync.py" + }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceAsyncClient", + "shortName": "DocumentServiceAsyncClient" + }, + "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceAsyncClient.update_document", + "method": { + "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService.UpdateDocument", + "service": { + "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService", + "shortName": "DocumentService" + }, + "shortName": "UpdateDocument" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.discoveryengine_v1alpha.types.UpdateDocumentRequest" + }, + { + "name": "document", + "type": "google.cloud.discoveryengine_v1alpha.types.Document" + }, + { + "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.discoveryengine_v1alpha.types.Document", + "shortName": "update_document" + }, + "description": "Sample for UpdateDocument", + "file": "discoveryengine_v1alpha_generated_document_service_update_document_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "discoveryengine_v1alpha_generated_DocumentService_UpdateDocument_async", + "segments": [ + { + "end": 50, + "start": 27, + "type": "FULL" + }, + { + "end": 50, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 44, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 47, + "start": 45, + "type": "REQUEST_EXECUTION" + }, + { + "end": 51, + "start": 48, + "type": "RESPONSE_HANDLING" + } + ], + "title": "discoveryengine_v1alpha_generated_document_service_update_document_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceClient", + "shortName": "DocumentServiceClient" + }, + "fullName": "google.cloud.discoveryengine_v1alpha.DocumentServiceClient.update_document", + "method": { + "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService.UpdateDocument", + "service": { + "fullName": "google.cloud.discoveryengine.v1alpha.DocumentService", + "shortName": "DocumentService" + }, + "shortName": "UpdateDocument" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.discoveryengine_v1alpha.types.UpdateDocumentRequest" + }, + { + "name": "document", + "type": "google.cloud.discoveryengine_v1alpha.types.Document" + }, + { + "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.discoveryengine_v1alpha.types.Document", + "shortName": "update_document" + }, + "description": "Sample for UpdateDocument", + "file": "discoveryengine_v1alpha_generated_document_service_update_document_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "discoveryengine_v1alpha_generated_DocumentService_UpdateDocument_sync", + "segments": [ + { + "end": 50, + "start": 27, + "type": "FULL" + }, + { + "end": 50, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 44, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 47, + "start": 45, + "type": "REQUEST_EXECUTION" + }, + { + "end": 51, + "start": 48, + "type": "RESPONSE_HANDLING" + } + ], + "title": "discoveryengine_v1alpha_generated_document_service_update_document_sync.py" + }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceAsyncClient", + "shortName": "EngineServiceAsyncClient" + }, + "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceAsyncClient.create_engine", + "method": { + "fullName": "google.cloud.discoveryengine.v1alpha.EngineService.CreateEngine", + "service": { + "fullName": "google.cloud.discoveryengine.v1alpha.EngineService", + "shortName": "EngineService" + }, + "shortName": "CreateEngine" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.discoveryengine_v1alpha.types.CreateEngineRequest" + }, + { + "name": "parent", + "type": "str" + }, + { + "name": "engine", + "type": "google.cloud.discoveryengine_v1alpha.types.Engine" + }, + { + "name": "engine_id", + "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": "create_engine" + }, + "description": "Sample for CreateEngine", + "file": "discoveryengine_v1alpha_generated_engine_service_create_engine_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "discoveryengine_v1alpha_generated_EngineService_CreateEngine_async", + "segments": [ + { + "end": 61, + "start": 27, + "type": "FULL" + }, + { + "end": 61, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 51, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 58, + "start": 52, + "type": "REQUEST_EXECUTION" + }, + { + "end": 62, + "start": 59, + "type": "RESPONSE_HANDLING" + } + ], + "title": "discoveryengine_v1alpha_generated_engine_service_create_engine_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceClient", + "shortName": "EngineServiceClient" + }, + "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceClient.create_engine", + "method": { + "fullName": "google.cloud.discoveryengine.v1alpha.EngineService.CreateEngine", + "service": { + "fullName": "google.cloud.discoveryengine.v1alpha.EngineService", + "shortName": "EngineService" + }, + "shortName": "CreateEngine" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.discoveryengine_v1alpha.types.CreateEngineRequest" + }, + { + "name": "parent", + "type": "str" + }, + { + "name": "engine", + "type": "google.cloud.discoveryengine_v1alpha.types.Engine" + }, + { + "name": "engine_id", + "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": "create_engine" + }, + "description": "Sample for CreateEngine", + "file": "discoveryengine_v1alpha_generated_engine_service_create_engine_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "discoveryengine_v1alpha_generated_EngineService_CreateEngine_sync", + "segments": [ + { + "end": 61, + "start": 27, + "type": "FULL" + }, + { + "end": 61, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 51, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 58, + "start": 52, + "type": "REQUEST_EXECUTION" + }, + { + "end": 62, + "start": 59, + "type": "RESPONSE_HANDLING" + } + ], + "title": "discoveryengine_v1alpha_generated_engine_service_create_engine_sync.py" + }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceAsyncClient", + "shortName": "EngineServiceAsyncClient" + }, + "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceAsyncClient.delete_engine", + "method": { + "fullName": "google.cloud.discoveryengine.v1alpha.EngineService.DeleteEngine", + "service": { + "fullName": "google.cloud.discoveryengine.v1alpha.EngineService", + "shortName": "EngineService" + }, + "shortName": "DeleteEngine" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.discoveryengine_v1alpha.types.DeleteEngineRequest" + }, + { + "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": "delete_engine" + }, + "description": "Sample for DeleteEngine", + "file": "discoveryengine_v1alpha_generated_engine_service_delete_engine_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "discoveryengine_v1alpha_generated_EngineService_DeleteEngine_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": "discoveryengine_v1alpha_generated_engine_service_delete_engine_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceClient", + "shortName": "EngineServiceClient" + }, + "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceClient.delete_engine", + "method": { + "fullName": "google.cloud.discoveryengine.v1alpha.EngineService.DeleteEngine", + "service": { + "fullName": "google.cloud.discoveryengine.v1alpha.EngineService", + "shortName": "EngineService" + }, + "shortName": "DeleteEngine" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.discoveryengine_v1alpha.types.DeleteEngineRequest" + }, + { + "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": "delete_engine" + }, + "description": "Sample for DeleteEngine", + "file": "discoveryengine_v1alpha_generated_engine_service_delete_engine_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "discoveryengine_v1alpha_generated_EngineService_DeleteEngine_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": "discoveryengine_v1alpha_generated_engine_service_delete_engine_sync.py" + }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceAsyncClient", + "shortName": "EngineServiceAsyncClient" + }, + "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceAsyncClient.get_engine", + "method": { + "fullName": "google.cloud.discoveryengine.v1alpha.EngineService.GetEngine", + "service": { + "fullName": "google.cloud.discoveryengine.v1alpha.EngineService", + "shortName": "EngineService" + }, + "shortName": "GetEngine" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.discoveryengine_v1alpha.types.GetEngineRequest" + }, + { + "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.discoveryengine_v1alpha.types.Engine", + "shortName": "get_engine" + }, + "description": "Sample for GetEngine", + "file": "discoveryengine_v1alpha_generated_engine_service_get_engine_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "discoveryengine_v1alpha_generated_EngineService_GetEngine_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": "discoveryengine_v1alpha_generated_engine_service_get_engine_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceClient", + "shortName": "EngineServiceClient" + }, + "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceClient.get_engine", + "method": { + "fullName": "google.cloud.discoveryengine.v1alpha.EngineService.GetEngine", + "service": { + "fullName": "google.cloud.discoveryengine.v1alpha.EngineService", + "shortName": "EngineService" + }, + "shortName": "GetEngine" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.discoveryengine_v1alpha.types.GetEngineRequest" + }, + { + "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.discoveryengine_v1alpha.types.Engine", + "shortName": "get_engine" + }, + "description": "Sample for GetEngine", + "file": "discoveryengine_v1alpha_generated_engine_service_get_engine_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "discoveryengine_v1alpha_generated_EngineService_GetEngine_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": "discoveryengine_v1alpha_generated_engine_service_get_engine_sync.py" + }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceAsyncClient", + "shortName": "EngineServiceAsyncClient" + }, + "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceAsyncClient.list_engines", + "method": { + "fullName": "google.cloud.discoveryengine.v1alpha.EngineService.ListEngines", + "service": { + "fullName": "google.cloud.discoveryengine.v1alpha.EngineService", + "shortName": "EngineService" + }, + "shortName": "ListEngines" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.discoveryengine_v1alpha.types.ListEnginesRequest" + }, + { + "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.discoveryengine_v1alpha.services.engine_service.pagers.ListEnginesAsyncPager", + "shortName": "list_engines" + }, + "description": "Sample for ListEngines", + "file": "discoveryengine_v1alpha_generated_engine_service_list_engines_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "discoveryengine_v1alpha_generated_EngineService_ListEngines_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": "discoveryengine_v1alpha_generated_engine_service_list_engines_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceClient", + "shortName": "EngineServiceClient" + }, + "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceClient.list_engines", + "method": { + "fullName": "google.cloud.discoveryengine.v1alpha.EngineService.ListEngines", + "service": { + "fullName": "google.cloud.discoveryengine.v1alpha.EngineService", + "shortName": "EngineService" + }, + "shortName": "ListEngines" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.discoveryengine_v1alpha.types.ListEnginesRequest" + }, + { + "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.discoveryengine_v1alpha.services.engine_service.pagers.ListEnginesPager", + "shortName": "list_engines" + }, + "description": "Sample for ListEngines", + "file": "discoveryengine_v1alpha_generated_engine_service_list_engines_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "discoveryengine_v1alpha_generated_EngineService_ListEngines_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": "discoveryengine_v1alpha_generated_engine_service_list_engines_sync.py" + }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceAsyncClient", + "shortName": "EngineServiceAsyncClient" + }, + "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceAsyncClient.pause_engine", + "method": { + "fullName": "google.cloud.discoveryengine.v1alpha.EngineService.PauseEngine", + "service": { + "fullName": "google.cloud.discoveryengine.v1alpha.EngineService", + "shortName": "EngineService" + }, + "shortName": "PauseEngine" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.discoveryengine_v1alpha.types.PauseEngineRequest" + }, + { + "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.discoveryengine_v1alpha.types.Engine", + "shortName": "pause_engine" + }, + "description": "Sample for PauseEngine", + "file": "discoveryengine_v1alpha_generated_engine_service_pause_engine_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "discoveryengine_v1alpha_generated_EngineService_PauseEngine_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": "discoveryengine_v1alpha_generated_engine_service_pause_engine_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceClient", + "shortName": "EngineServiceClient" + }, + "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceClient.pause_engine", + "method": { + "fullName": "google.cloud.discoveryengine.v1alpha.EngineService.PauseEngine", + "service": { + "fullName": "google.cloud.discoveryengine.v1alpha.EngineService", + "shortName": "EngineService" + }, + "shortName": "PauseEngine" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.discoveryengine_v1alpha.types.PauseEngineRequest" + }, + { + "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.discoveryengine_v1alpha.types.Engine", + "shortName": "pause_engine" + }, + "description": "Sample for PauseEngine", + "file": "discoveryengine_v1alpha_generated_engine_service_pause_engine_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "discoveryengine_v1alpha_generated_EngineService_PauseEngine_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": "discoveryengine_v1alpha_generated_engine_service_pause_engine_sync.py" + }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceAsyncClient", + "shortName": "EngineServiceAsyncClient" + }, + "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceAsyncClient.resume_engine", + "method": { + "fullName": "google.cloud.discoveryengine.v1alpha.EngineService.ResumeEngine", + "service": { + "fullName": "google.cloud.discoveryengine.v1alpha.EngineService", + "shortName": "EngineService" + }, + "shortName": "ResumeEngine" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.discoveryengine_v1alpha.types.ResumeEngineRequest" + }, + { + "name": "name", "type": "str" }, { @@ -4425,22 +6528,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.api_core.operation_async.AsyncOperation", - "shortName": "create_engine" + "resultType": "google.cloud.discoveryengine_v1alpha.types.Engine", + "shortName": "resume_engine" }, - "description": "Sample for CreateEngine", - "file": "discoveryengine_v1alpha_generated_engine_service_create_engine_async.py", + "description": "Sample for ResumeEngine", + "file": "discoveryengine_v1alpha_generated_engine_service_resume_engine_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_EngineService_CreateEngine_async", + "regionTag": "discoveryengine_v1alpha_generated_EngineService_ResumeEngine_async", "segments": [ { - "end": 61, + "end": 51, "start": 27, "type": "FULL" }, { - "end": 61, + "end": 51, "start": 27, "type": "SHORT" }, @@ -4450,22 +6553,22 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 51, + "end": 45, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 58, - "start": 52, + "end": 48, + "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 62, - "start": 59, + "end": 52, + "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_engine_service_create_engine_async.py" + "title": "discoveryengine_v1alpha_generated_engine_service_resume_engine_async.py" }, { "canonical": true, @@ -4474,30 +6577,22 @@ "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceClient", "shortName": "EngineServiceClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceClient.create_engine", + "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceClient.resume_engine", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.EngineService.CreateEngine", + "fullName": "google.cloud.discoveryengine.v1alpha.EngineService.ResumeEngine", "service": { "fullName": "google.cloud.discoveryengine.v1alpha.EngineService", "shortName": "EngineService" }, - "shortName": "CreateEngine" + "shortName": "ResumeEngine" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.CreateEngineRequest" - }, - { - "name": "parent", - "type": "str" - }, - { - "name": "engine", - "type": "google.cloud.discoveryengine_v1alpha.types.Engine" + "type": "google.cloud.discoveryengine_v1alpha.types.ResumeEngineRequest" }, { - "name": "engine_id", + "name": "name", "type": "str" }, { @@ -4513,22 +6608,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.api_core.operation.Operation", - "shortName": "create_engine" + "resultType": "google.cloud.discoveryengine_v1alpha.types.Engine", + "shortName": "resume_engine" }, - "description": "Sample for CreateEngine", - "file": "discoveryengine_v1alpha_generated_engine_service_create_engine_sync.py", + "description": "Sample for ResumeEngine", + "file": "discoveryengine_v1alpha_generated_engine_service_resume_engine_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_EngineService_CreateEngine_sync", + "regionTag": "discoveryengine_v1alpha_generated_EngineService_ResumeEngine_sync", "segments": [ { - "end": 61, + "end": 51, "start": 27, "type": "FULL" }, { - "end": 61, + "end": 51, "start": 27, "type": "SHORT" }, @@ -4538,22 +6633,22 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 51, + "end": 45, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 58, - "start": 52, + "end": 48, + "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 62, - "start": 59, + "end": 52, + "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_engine_service_create_engine_sync.py" + "title": "discoveryengine_v1alpha_generated_engine_service_resume_engine_sync.py" }, { "canonical": true, @@ -4563,19 +6658,19 @@ "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceAsyncClient", "shortName": "EngineServiceAsyncClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceAsyncClient.delete_engine", + "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceAsyncClient.tune_engine", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.EngineService.DeleteEngine", + "fullName": "google.cloud.discoveryengine.v1alpha.EngineService.TuneEngine", "service": { "fullName": "google.cloud.discoveryengine.v1alpha.EngineService", "shortName": "EngineService" }, - "shortName": "DeleteEngine" + "shortName": "TuneEngine" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.DeleteEngineRequest" + "type": "google.cloud.discoveryengine_v1alpha.types.TuneEngineRequest" }, { "name": "name", @@ -4595,13 +6690,13 @@ } ], "resultType": "google.api_core.operation_async.AsyncOperation", - "shortName": "delete_engine" + "shortName": "tune_engine" }, - "description": "Sample for DeleteEngine", - "file": "discoveryengine_v1alpha_generated_engine_service_delete_engine_async.py", + "description": "Sample for TuneEngine", + "file": "discoveryengine_v1alpha_generated_engine_service_tune_engine_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_EngineService_DeleteEngine_async", + "regionTag": "discoveryengine_v1alpha_generated_EngineService_TuneEngine_async", "segments": [ { "end": 55, @@ -4634,7 +6729,7 @@ "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_engine_service_delete_engine_async.py" + "title": "discoveryengine_v1alpha_generated_engine_service_tune_engine_async.py" }, { "canonical": true, @@ -4643,19 +6738,19 @@ "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceClient", "shortName": "EngineServiceClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceClient.delete_engine", + "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceClient.tune_engine", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.EngineService.DeleteEngine", + "fullName": "google.cloud.discoveryengine.v1alpha.EngineService.TuneEngine", "service": { "fullName": "google.cloud.discoveryengine.v1alpha.EngineService", "shortName": "EngineService" }, - "shortName": "DeleteEngine" + "shortName": "TuneEngine" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.DeleteEngineRequest" + "type": "google.cloud.discoveryengine_v1alpha.types.TuneEngineRequest" }, { "name": "name", @@ -4675,13 +6770,13 @@ } ], "resultType": "google.api_core.operation.Operation", - "shortName": "delete_engine" + "shortName": "tune_engine" }, - "description": "Sample for DeleteEngine", - "file": "discoveryengine_v1alpha_generated_engine_service_delete_engine_sync.py", + "description": "Sample for TuneEngine", + "file": "discoveryengine_v1alpha_generated_engine_service_tune_engine_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_EngineService_DeleteEngine_sync", + "regionTag": "discoveryengine_v1alpha_generated_EngineService_TuneEngine_sync", "segments": [ { "end": 55, @@ -4714,7 +6809,7 @@ "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_engine_service_delete_engine_sync.py" + "title": "discoveryengine_v1alpha_generated_engine_service_tune_engine_sync.py" }, { "canonical": true, @@ -4724,23 +6819,27 @@ "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceAsyncClient", "shortName": "EngineServiceAsyncClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceAsyncClient.get_engine", + "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceAsyncClient.update_engine", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.EngineService.GetEngine", + "fullName": "google.cloud.discoveryengine.v1alpha.EngineService.UpdateEngine", "service": { "fullName": "google.cloud.discoveryengine.v1alpha.EngineService", "shortName": "EngineService" }, - "shortName": "GetEngine" + "shortName": "UpdateEngine" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.GetEngineRequest" + "type": "google.cloud.discoveryengine_v1alpha.types.UpdateEngineRequest" }, { - "name": "name", - "type": "str" + "name": "engine", + "type": "google.cloud.discoveryengine_v1alpha.types.Engine" + }, + { + "name": "update_mask", + "type": "google.protobuf.field_mask_pb2.FieldMask" }, { "name": "retry", @@ -4756,21 +6855,21 @@ } ], "resultType": "google.cloud.discoveryengine_v1alpha.types.Engine", - "shortName": "get_engine" + "shortName": "update_engine" }, - "description": "Sample for GetEngine", - "file": "discoveryengine_v1alpha_generated_engine_service_get_engine_async.py", + "description": "Sample for UpdateEngine", + "file": "discoveryengine_v1alpha_generated_engine_service_update_engine_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_EngineService_GetEngine_async", + "regionTag": "discoveryengine_v1alpha_generated_EngineService_UpdateEngine_async", "segments": [ { - "end": 51, + "end": 55, "start": 27, "type": "FULL" }, { - "end": 51, + "end": 55, "start": 27, "type": "SHORT" }, @@ -4780,22 +6879,22 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 45, + "end": 49, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 48, - "start": 46, + "end": 52, + "start": 50, "type": "REQUEST_EXECUTION" }, { - "end": 52, - "start": 49, + "end": 56, + "start": 53, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_engine_service_get_engine_async.py" + "title": "discoveryengine_v1alpha_generated_engine_service_update_engine_async.py" }, { "canonical": true, @@ -4804,23 +6903,27 @@ "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceClient", "shortName": "EngineServiceClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceClient.get_engine", + "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceClient.update_engine", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.EngineService.GetEngine", + "fullName": "google.cloud.discoveryengine.v1alpha.EngineService.UpdateEngine", "service": { "fullName": "google.cloud.discoveryengine.v1alpha.EngineService", "shortName": "EngineService" }, - "shortName": "GetEngine" + "shortName": "UpdateEngine" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.GetEngineRequest" + "type": "google.cloud.discoveryengine_v1alpha.types.UpdateEngineRequest" }, { - "name": "name", - "type": "str" + "name": "engine", + "type": "google.cloud.discoveryengine_v1alpha.types.Engine" + }, + { + "name": "update_mask", + "type": "google.protobuf.field_mask_pb2.FieldMask" }, { "name": "retry", @@ -4836,21 +6939,21 @@ } ], "resultType": "google.cloud.discoveryengine_v1alpha.types.Engine", - "shortName": "get_engine" + "shortName": "update_engine" }, - "description": "Sample for GetEngine", - "file": "discoveryengine_v1alpha_generated_engine_service_get_engine_sync.py", + "description": "Sample for UpdateEngine", + "file": "discoveryengine_v1alpha_generated_engine_service_update_engine_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_EngineService_GetEngine_sync", + "regionTag": "discoveryengine_v1alpha_generated_EngineService_UpdateEngine_sync", "segments": [ { - "end": 51, + "end": 55, "start": 27, "type": "FULL" }, { - "end": 51, + "end": 55, "start": 27, "type": "SHORT" }, @@ -4860,48 +6963,44 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 45, + "end": 49, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 48, - "start": 46, + "end": 52, + "start": 50, "type": "REQUEST_EXECUTION" }, { - "end": 52, - "start": 49, + "end": 56, + "start": 53, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_engine_service_get_engine_sync.py" + "title": "discoveryengine_v1alpha_generated_engine_service_update_engine_sync.py" }, { "canonical": true, "clientMethod": { "async": true, "client": { - "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceAsyncClient", - "shortName": "EngineServiceAsyncClient" + "fullName": "google.cloud.discoveryengine_v1alpha.EstimateBillingServiceAsyncClient", + "shortName": "EstimateBillingServiceAsyncClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceAsyncClient.list_engines", + "fullName": "google.cloud.discoveryengine_v1alpha.EstimateBillingServiceAsyncClient.estimate_data_size", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.EngineService.ListEngines", + "fullName": "google.cloud.discoveryengine.v1alpha.EstimateBillingService.EstimateDataSize", "service": { - "fullName": "google.cloud.discoveryengine.v1alpha.EngineService", - "shortName": "EngineService" + "fullName": "google.cloud.discoveryengine.v1alpha.EstimateBillingService", + "shortName": "EstimateBillingService" }, - "shortName": "ListEngines" + "shortName": "EstimateDataSize" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.ListEnginesRequest" - }, - { - "name": "parent", - "type": "str" + "type": "google.cloud.discoveryengine_v1alpha.types.EstimateDataSizeRequest" }, { "name": "retry", @@ -4916,22 +7015,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1alpha.services.engine_service.pagers.ListEnginesAsyncPager", - "shortName": "list_engines" + "resultType": "google.api_core.operation_async.AsyncOperation", + "shortName": "estimate_data_size" }, - "description": "Sample for ListEngines", - "file": "discoveryengine_v1alpha_generated_engine_service_list_engines_async.py", + "description": "Sample for EstimateDataSize", + "file": "discoveryengine_v1alpha_generated_estimate_billing_service_estimate_data_size_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_EngineService_ListEngines_async", + "regionTag": "discoveryengine_v1alpha_generated_EstimateBillingService_EstimateDataSize_async", "segments": [ { - "end": 52, + "end": 55, "start": 27, "type": "FULL" }, { - "end": 52, + "end": 55, "start": 27, "type": "SHORT" }, @@ -4946,42 +7045,38 @@ "type": "REQUEST_INITIALIZATION" }, { - "end": 48, + "end": 52, "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 53, - "start": 49, + "end": 56, + "start": 53, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_engine_service_list_engines_async.py" + "title": "discoveryengine_v1alpha_generated_estimate_billing_service_estimate_data_size_async.py" }, { "canonical": true, "clientMethod": { "client": { - "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceClient", - "shortName": "EngineServiceClient" + "fullName": "google.cloud.discoveryengine_v1alpha.EstimateBillingServiceClient", + "shortName": "EstimateBillingServiceClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceClient.list_engines", + "fullName": "google.cloud.discoveryengine_v1alpha.EstimateBillingServiceClient.estimate_data_size", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.EngineService.ListEngines", + "fullName": "google.cloud.discoveryengine.v1alpha.EstimateBillingService.EstimateDataSize", "service": { - "fullName": "google.cloud.discoveryengine.v1alpha.EngineService", - "shortName": "EngineService" + "fullName": "google.cloud.discoveryengine.v1alpha.EstimateBillingService", + "shortName": "EstimateBillingService" }, - "shortName": "ListEngines" + "shortName": "EstimateDataSize" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.ListEnginesRequest" - }, - { - "name": "parent", - "type": "str" + "type": "google.cloud.discoveryengine_v1alpha.types.EstimateDataSizeRequest" }, { "name": "retry", @@ -4996,22 +7091,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1alpha.services.engine_service.pagers.ListEnginesPager", - "shortName": "list_engines" + "resultType": "google.api_core.operation.Operation", + "shortName": "estimate_data_size" }, - "description": "Sample for ListEngines", - "file": "discoveryengine_v1alpha_generated_engine_service_list_engines_sync.py", + "description": "Sample for EstimateDataSize", + "file": "discoveryengine_v1alpha_generated_estimate_billing_service_estimate_data_size_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_EngineService_ListEngines_sync", + "regionTag": "discoveryengine_v1alpha_generated_EstimateBillingService_EstimateDataSize_sync", "segments": [ { - "end": 52, + "end": 55, "start": 27, "type": "FULL" }, { - "end": 52, + "end": 55, "start": 27, "type": "SHORT" }, @@ -5026,43 +7121,39 @@ "type": "REQUEST_INITIALIZATION" }, { - "end": 48, + "end": 52, "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 53, - "start": 49, + "end": 56, + "start": 53, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_engine_service_list_engines_sync.py" + "title": "discoveryengine_v1alpha_generated_estimate_billing_service_estimate_data_size_sync.py" }, { "canonical": true, "clientMethod": { "async": true, "client": { - "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceAsyncClient", - "shortName": "EngineServiceAsyncClient" + "fullName": "google.cloud.discoveryengine_v1alpha.GroundedGenerationServiceAsyncClient", + "shortName": "GroundedGenerationServiceAsyncClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceAsyncClient.pause_engine", + "fullName": "google.cloud.discoveryengine_v1alpha.GroundedGenerationServiceAsyncClient.check_grounding", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.EngineService.PauseEngine", + "fullName": "google.cloud.discoveryengine.v1alpha.GroundedGenerationService.CheckGrounding", "service": { - "fullName": "google.cloud.discoveryengine.v1alpha.EngineService", - "shortName": "EngineService" + "fullName": "google.cloud.discoveryengine.v1alpha.GroundedGenerationService", + "shortName": "GroundedGenerationService" }, - "shortName": "PauseEngine" + "shortName": "CheckGrounding" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.PauseEngineRequest" - }, - { - "name": "name", - "type": "str" + "type": "google.cloud.discoveryengine_v1alpha.types.CheckGroundingRequest" }, { "name": "retry", @@ -5077,14 +7168,14 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1alpha.types.Engine", - "shortName": "pause_engine" + "resultType": "google.cloud.discoveryengine_v1alpha.types.CheckGroundingResponse", + "shortName": "check_grounding" }, - "description": "Sample for PauseEngine", - "file": "discoveryengine_v1alpha_generated_engine_service_pause_engine_async.py", + "description": "Sample for CheckGrounding", + "file": "discoveryengine_v1alpha_generated_grounded_generation_service_check_grounding_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_EngineService_PauseEngine_async", + "regionTag": "discoveryengine_v1alpha_generated_GroundedGenerationService_CheckGrounding_async", "segments": [ { "end": 51, @@ -5117,32 +7208,28 @@ "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_engine_service_pause_engine_async.py" + "title": "discoveryengine_v1alpha_generated_grounded_generation_service_check_grounding_async.py" }, { "canonical": true, "clientMethod": { "client": { - "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceClient", - "shortName": "EngineServiceClient" + "fullName": "google.cloud.discoveryengine_v1alpha.GroundedGenerationServiceClient", + "shortName": "GroundedGenerationServiceClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceClient.pause_engine", + "fullName": "google.cloud.discoveryengine_v1alpha.GroundedGenerationServiceClient.check_grounding", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.EngineService.PauseEngine", + "fullName": "google.cloud.discoveryengine.v1alpha.GroundedGenerationService.CheckGrounding", "service": { - "fullName": "google.cloud.discoveryengine.v1alpha.EngineService", - "shortName": "EngineService" + "fullName": "google.cloud.discoveryengine.v1alpha.GroundedGenerationService", + "shortName": "GroundedGenerationService" }, - "shortName": "PauseEngine" + "shortName": "CheckGrounding" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.PauseEngineRequest" - }, - { - "name": "name", - "type": "str" + "type": "google.cloud.discoveryengine_v1alpha.types.CheckGroundingRequest" }, { "name": "retry", @@ -5157,14 +7244,14 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1alpha.types.Engine", - "shortName": "pause_engine" + "resultType": "google.cloud.discoveryengine_v1alpha.types.CheckGroundingResponse", + "shortName": "check_grounding" }, - "description": "Sample for PauseEngine", - "file": "discoveryengine_v1alpha_generated_engine_service_pause_engine_sync.py", + "description": "Sample for CheckGrounding", + "file": "discoveryengine_v1alpha_generated_grounded_generation_service_check_grounding_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_EngineService_PauseEngine_sync", + "regionTag": "discoveryengine_v1alpha_generated_GroundedGenerationService_CheckGrounding_sync", "segments": [ { "end": 51, @@ -5197,29 +7284,29 @@ "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_engine_service_pause_engine_sync.py" + "title": "discoveryengine_v1alpha_generated_grounded_generation_service_check_grounding_sync.py" }, { "canonical": true, "clientMethod": { "async": true, "client": { - "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceAsyncClient", - "shortName": "EngineServiceAsyncClient" + "fullName": "google.cloud.discoveryengine_v1alpha.ProjectServiceAsyncClient", + "shortName": "ProjectServiceAsyncClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceAsyncClient.resume_engine", + "fullName": "google.cloud.discoveryengine_v1alpha.ProjectServiceAsyncClient.get_project", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.EngineService.ResumeEngine", + "fullName": "google.cloud.discoveryengine.v1alpha.ProjectService.GetProject", "service": { - "fullName": "google.cloud.discoveryengine.v1alpha.EngineService", - "shortName": "EngineService" + "fullName": "google.cloud.discoveryengine.v1alpha.ProjectService", + "shortName": "ProjectService" }, - "shortName": "ResumeEngine" + "shortName": "GetProject" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.ResumeEngineRequest" + "type": "google.cloud.discoveryengine_v1alpha.types.GetProjectRequest" }, { "name": "name", @@ -5238,14 +7325,14 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1alpha.types.Engine", - "shortName": "resume_engine" + "resultType": "google.cloud.discoveryengine_v1alpha.types.Project", + "shortName": "get_project" }, - "description": "Sample for ResumeEngine", - "file": "discoveryengine_v1alpha_generated_engine_service_resume_engine_async.py", + "description": "Sample for GetProject", + "file": "discoveryengine_v1alpha_generated_project_service_get_project_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_EngineService_ResumeEngine_async", + "regionTag": "discoveryengine_v1alpha_generated_ProjectService_GetProject_async", "segments": [ { "end": 51, @@ -5278,28 +7365,28 @@ "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_engine_service_resume_engine_async.py" + "title": "discoveryengine_v1alpha_generated_project_service_get_project_async.py" }, { "canonical": true, "clientMethod": { "client": { - "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceClient", - "shortName": "EngineServiceClient" + "fullName": "google.cloud.discoveryengine_v1alpha.ProjectServiceClient", + "shortName": "ProjectServiceClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceClient.resume_engine", + "fullName": "google.cloud.discoveryengine_v1alpha.ProjectServiceClient.get_project", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.EngineService.ResumeEngine", + "fullName": "google.cloud.discoveryengine.v1alpha.ProjectService.GetProject", "service": { - "fullName": "google.cloud.discoveryengine.v1alpha.EngineService", - "shortName": "EngineService" + "fullName": "google.cloud.discoveryengine.v1alpha.ProjectService", + "shortName": "ProjectService" }, - "shortName": "ResumeEngine" + "shortName": "GetProject" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.ResumeEngineRequest" + "type": "google.cloud.discoveryengine_v1alpha.types.GetProjectRequest" }, { "name": "name", @@ -5318,14 +7405,14 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1alpha.types.Engine", - "shortName": "resume_engine" + "resultType": "google.cloud.discoveryengine_v1alpha.types.Project", + "shortName": "get_project" }, - "description": "Sample for ResumeEngine", - "file": "discoveryengine_v1alpha_generated_engine_service_resume_engine_sync.py", + "description": "Sample for GetProject", + "file": "discoveryengine_v1alpha_generated_project_service_get_project_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_EngineService_ResumeEngine_sync", + "regionTag": "discoveryengine_v1alpha_generated_ProjectService_GetProject_sync", "segments": [ { "end": 51, @@ -5358,29 +7445,29 @@ "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_engine_service_resume_engine_sync.py" + "title": "discoveryengine_v1alpha_generated_project_service_get_project_sync.py" }, { "canonical": true, "clientMethod": { "async": true, "client": { - "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceAsyncClient", - "shortName": "EngineServiceAsyncClient" + "fullName": "google.cloud.discoveryengine_v1alpha.ProjectServiceAsyncClient", + "shortName": "ProjectServiceAsyncClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceAsyncClient.tune_engine", + "fullName": "google.cloud.discoveryengine_v1alpha.ProjectServiceAsyncClient.provision_project", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.EngineService.TuneEngine", + "fullName": "google.cloud.discoveryengine.v1alpha.ProjectService.ProvisionProject", "service": { - "fullName": "google.cloud.discoveryengine.v1alpha.EngineService", - "shortName": "EngineService" + "fullName": "google.cloud.discoveryengine.v1alpha.ProjectService", + "shortName": "ProjectService" }, - "shortName": "TuneEngine" + "shortName": "ProvisionProject" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.TuneEngineRequest" + "type": "google.cloud.discoveryengine_v1alpha.types.ProvisionProjectRequest" }, { "name": "name", @@ -5400,21 +7487,21 @@ } ], "resultType": "google.api_core.operation_async.AsyncOperation", - "shortName": "tune_engine" + "shortName": "provision_project" }, - "description": "Sample for TuneEngine", - "file": "discoveryengine_v1alpha_generated_engine_service_tune_engine_async.py", + "description": "Sample for ProvisionProject", + "file": "discoveryengine_v1alpha_generated_project_service_provision_project_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_EngineService_TuneEngine_async", + "regionTag": "discoveryengine_v1alpha_generated_ProjectService_ProvisionProject_async", "segments": [ { - "end": 55, + "end": 57, "start": 27, "type": "FULL" }, { - "end": 55, + "end": 57, "start": 27, "type": "SHORT" }, @@ -5424,43 +7511,43 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 45, + "end": 47, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 52, - "start": 46, + "end": 54, + "start": 48, "type": "REQUEST_EXECUTION" }, { - "end": 56, - "start": 53, + "end": 58, + "start": 55, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_engine_service_tune_engine_async.py" + "title": "discoveryengine_v1alpha_generated_project_service_provision_project_async.py" }, { "canonical": true, "clientMethod": { "client": { - "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceClient", - "shortName": "EngineServiceClient" + "fullName": "google.cloud.discoveryengine_v1alpha.ProjectServiceClient", + "shortName": "ProjectServiceClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceClient.tune_engine", + "fullName": "google.cloud.discoveryengine_v1alpha.ProjectServiceClient.provision_project", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.EngineService.TuneEngine", + "fullName": "google.cloud.discoveryengine.v1alpha.ProjectService.ProvisionProject", "service": { - "fullName": "google.cloud.discoveryengine.v1alpha.EngineService", - "shortName": "EngineService" + "fullName": "google.cloud.discoveryengine.v1alpha.ProjectService", + "shortName": "ProjectService" }, - "shortName": "TuneEngine" + "shortName": "ProvisionProject" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.TuneEngineRequest" + "type": "google.cloud.discoveryengine_v1alpha.types.ProvisionProjectRequest" }, { "name": "name", @@ -5480,21 +7567,21 @@ } ], "resultType": "google.api_core.operation.Operation", - "shortName": "tune_engine" + "shortName": "provision_project" }, - "description": "Sample for TuneEngine", - "file": "discoveryengine_v1alpha_generated_engine_service_tune_engine_sync.py", + "description": "Sample for ProvisionProject", + "file": "discoveryengine_v1alpha_generated_project_service_provision_project_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_EngineService_TuneEngine_sync", + "regionTag": "discoveryengine_v1alpha_generated_ProjectService_ProvisionProject_sync", "segments": [ { - "end": 55, + "end": 57, "start": 27, "type": "FULL" }, { - "end": 55, + "end": 57, "start": 27, "type": "SHORT" }, @@ -5504,52 +7591,60 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 45, + "end": 47, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 52, - "start": 46, + "end": 54, + "start": 48, "type": "REQUEST_EXECUTION" }, { - "end": 56, - "start": 53, + "end": 58, + "start": 55, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_engine_service_tune_engine_sync.py" + "title": "discoveryengine_v1alpha_generated_project_service_provision_project_sync.py" }, { "canonical": true, "clientMethod": { "async": true, "client": { - "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceAsyncClient", - "shortName": "EngineServiceAsyncClient" + "fullName": "google.cloud.discoveryengine_v1alpha.ProjectServiceAsyncClient", + "shortName": "ProjectServiceAsyncClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceAsyncClient.update_engine", + "fullName": "google.cloud.discoveryengine_v1alpha.ProjectServiceAsyncClient.report_consent_change", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.EngineService.UpdateEngine", + "fullName": "google.cloud.discoveryengine.v1alpha.ProjectService.ReportConsentChange", "service": { - "fullName": "google.cloud.discoveryengine.v1alpha.EngineService", - "shortName": "EngineService" + "fullName": "google.cloud.discoveryengine.v1alpha.ProjectService", + "shortName": "ProjectService" }, - "shortName": "UpdateEngine" + "shortName": "ReportConsentChange" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.UpdateEngineRequest" + "type": "google.cloud.discoveryengine_v1alpha.types.ReportConsentChangeRequest" }, { - "name": "engine", - "type": "google.cloud.discoveryengine_v1alpha.types.Engine" + "name": "consent_change_action", + "type": "google.cloud.discoveryengine_v1alpha.types.ReportConsentChangeRequest.ConsentChangeAction" }, { - "name": "update_mask", - "type": "google.protobuf.field_mask_pb2.FieldMask" + "name": "project", + "type": "str" + }, + { + "name": "service_term_id", + "type": "str" + }, + { + "name": "service_term_version", + "type": "str" }, { "name": "retry", @@ -5564,22 +7659,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1alpha.types.Engine", - "shortName": "update_engine" + "resultType": "google.cloud.discoveryengine_v1alpha.types.Project", + "shortName": "report_consent_change" }, - "description": "Sample for UpdateEngine", - "file": "discoveryengine_v1alpha_generated_engine_service_update_engine_async.py", + "description": "Sample for ReportConsentChange", + "file": "discoveryengine_v1alpha_generated_project_service_report_consent_change_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_EngineService_UpdateEngine_async", + "regionTag": "discoveryengine_v1alpha_generated_ProjectService_ReportConsentChange_async", "segments": [ { - "end": 55, + "end": 54, "start": 27, "type": "FULL" }, { - "end": 55, + "end": 54, "start": 27, "type": "SHORT" }, @@ -5589,51 +7684,59 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 49, + "end": 48, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 52, - "start": 50, + "end": 51, + "start": 49, "type": "REQUEST_EXECUTION" }, { - "end": 56, - "start": 53, + "end": 55, + "start": 52, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_engine_service_update_engine_async.py" + "title": "discoveryengine_v1alpha_generated_project_service_report_consent_change_async.py" }, { "canonical": true, "clientMethod": { "client": { - "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceClient", - "shortName": "EngineServiceClient" + "fullName": "google.cloud.discoveryengine_v1alpha.ProjectServiceClient", + "shortName": "ProjectServiceClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.EngineServiceClient.update_engine", + "fullName": "google.cloud.discoveryengine_v1alpha.ProjectServiceClient.report_consent_change", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.EngineService.UpdateEngine", + "fullName": "google.cloud.discoveryengine.v1alpha.ProjectService.ReportConsentChange", "service": { - "fullName": "google.cloud.discoveryengine.v1alpha.EngineService", - "shortName": "EngineService" + "fullName": "google.cloud.discoveryengine.v1alpha.ProjectService", + "shortName": "ProjectService" }, - "shortName": "UpdateEngine" + "shortName": "ReportConsentChange" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.UpdateEngineRequest" + "type": "google.cloud.discoveryengine_v1alpha.types.ReportConsentChangeRequest" }, { - "name": "engine", - "type": "google.cloud.discoveryengine_v1alpha.types.Engine" + "name": "consent_change_action", + "type": "google.cloud.discoveryengine_v1alpha.types.ReportConsentChangeRequest.ConsentChangeAction" }, { - "name": "update_mask", - "type": "google.protobuf.field_mask_pb2.FieldMask" + "name": "project", + "type": "str" + }, + { + "name": "service_term_id", + "type": "str" + }, + { + "name": "service_term_version", + "type": "str" }, { "name": "retry", @@ -5648,22 +7751,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1alpha.types.Engine", - "shortName": "update_engine" + "resultType": "google.cloud.discoveryengine_v1alpha.types.Project", + "shortName": "report_consent_change" }, - "description": "Sample for UpdateEngine", - "file": "discoveryengine_v1alpha_generated_engine_service_update_engine_sync.py", + "description": "Sample for ReportConsentChange", + "file": "discoveryengine_v1alpha_generated_project_service_report_consent_change_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_EngineService_UpdateEngine_sync", + "regionTag": "discoveryengine_v1alpha_generated_ProjectService_ReportConsentChange_sync", "segments": [ { - "end": 55, + "end": 54, "start": 27, "type": "FULL" }, { - "end": 55, + "end": 54, "start": 27, "type": "SHORT" }, @@ -5673,44 +7776,44 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 49, + "end": 48, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 52, - "start": 50, + "end": 51, + "start": 49, "type": "REQUEST_EXECUTION" }, { - "end": 56, - "start": 53, + "end": 55, + "start": 52, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_engine_service_update_engine_sync.py" + "title": "discoveryengine_v1alpha_generated_project_service_report_consent_change_sync.py" }, { "canonical": true, "clientMethod": { "async": true, "client": { - "fullName": "google.cloud.discoveryengine_v1alpha.EstimateBillingServiceAsyncClient", - "shortName": "EstimateBillingServiceAsyncClient" + "fullName": "google.cloud.discoveryengine_v1alpha.RankServiceAsyncClient", + "shortName": "RankServiceAsyncClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.EstimateBillingServiceAsyncClient.estimate_data_size", + "fullName": "google.cloud.discoveryengine_v1alpha.RankServiceAsyncClient.rank", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.EstimateBillingService.EstimateDataSize", + "fullName": "google.cloud.discoveryengine.v1alpha.RankService.Rank", "service": { - "fullName": "google.cloud.discoveryengine.v1alpha.EstimateBillingService", - "shortName": "EstimateBillingService" + "fullName": "google.cloud.discoveryengine.v1alpha.RankService", + "shortName": "RankService" }, - "shortName": "EstimateDataSize" + "shortName": "Rank" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.EstimateDataSizeRequest" + "type": "google.cloud.discoveryengine_v1alpha.types.RankRequest" }, { "name": "retry", @@ -5725,22 +7828,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.api_core.operation_async.AsyncOperation", - "shortName": "estimate_data_size" + "resultType": "google.cloud.discoveryengine_v1alpha.types.RankResponse", + "shortName": "rank" }, - "description": "Sample for EstimateDataSize", - "file": "discoveryengine_v1alpha_generated_estimate_billing_service_estimate_data_size_async.py", + "description": "Sample for Rank", + "file": "discoveryengine_v1alpha_generated_rank_service_rank_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_EstimateBillingService_EstimateDataSize_async", + "regionTag": "discoveryengine_v1alpha_generated_RankService_Rank_async", "segments": [ { - "end": 55, + "end": 51, "start": 27, "type": "FULL" }, { - "end": 55, + "end": 51, "start": 27, "type": "SHORT" }, @@ -5755,38 +7858,38 @@ "type": "REQUEST_INITIALIZATION" }, { - "end": 52, + "end": 48, "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 56, - "start": 53, + "end": 52, + "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_estimate_billing_service_estimate_data_size_async.py" + "title": "discoveryengine_v1alpha_generated_rank_service_rank_async.py" }, { "canonical": true, "clientMethod": { "client": { - "fullName": "google.cloud.discoveryengine_v1alpha.EstimateBillingServiceClient", - "shortName": "EstimateBillingServiceClient" + "fullName": "google.cloud.discoveryengine_v1alpha.RankServiceClient", + "shortName": "RankServiceClient" }, - "fullName": "google.cloud.discoveryengine_v1alpha.EstimateBillingServiceClient.estimate_data_size", + "fullName": "google.cloud.discoveryengine_v1alpha.RankServiceClient.rank", "method": { - "fullName": "google.cloud.discoveryengine.v1alpha.EstimateBillingService.EstimateDataSize", + "fullName": "google.cloud.discoveryengine.v1alpha.RankService.Rank", "service": { - "fullName": "google.cloud.discoveryengine.v1alpha.EstimateBillingService", - "shortName": "EstimateBillingService" + "fullName": "google.cloud.discoveryengine.v1alpha.RankService", + "shortName": "RankService" }, - "shortName": "EstimateDataSize" + "shortName": "Rank" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1alpha.types.EstimateDataSizeRequest" + "type": "google.cloud.discoveryengine_v1alpha.types.RankRequest" }, { "name": "retry", @@ -5801,22 +7904,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.api_core.operation.Operation", - "shortName": "estimate_data_size" + "resultType": "google.cloud.discoveryengine_v1alpha.types.RankResponse", + "shortName": "rank" }, - "description": "Sample for EstimateDataSize", - "file": "discoveryengine_v1alpha_generated_estimate_billing_service_estimate_data_size_sync.py", + "description": "Sample for Rank", + "file": "discoveryengine_v1alpha_generated_rank_service_rank_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1alpha_generated_EstimateBillingService_EstimateDataSize_sync", + "regionTag": "discoveryengine_v1alpha_generated_RankService_Rank_sync", "segments": [ { - "end": 55, + "end": 51, "start": 27, "type": "FULL" }, { - "end": 55, + "end": 51, "start": 27, "type": "SHORT" }, @@ -5831,17 +7934,17 @@ "type": "REQUEST_INITIALIZATION" }, { - "end": 52, + "end": 48, "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 56, - "start": 53, + "end": 52, + "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1alpha_generated_estimate_billing_service_estimate_data_size_sync.py" + "title": "discoveryengine_v1alpha_generated_rank_service_rank_sync.py" }, { "canonical": true, diff --git a/packages/google-cloud-discoveryengine/samples/generated_samples/snippet_metadata_google.cloud.discoveryengine.v1beta.json b/packages/google-cloud-discoveryengine/samples/generated_samples/snippet_metadata_google.cloud.discoveryengine.v1beta.json index afa2c11cf287..3e0ce89ad871 100644 --- a/packages/google-cloud-discoveryengine/samples/generated_samples/snippet_metadata_google.cloud.discoveryengine.v1beta.json +++ b/packages/google-cloud-discoveryengine/samples/generated_samples/snippet_metadata_google.cloud.discoveryengine.v1beta.json @@ -470,6 +470,159 @@ ], "title": "discoveryengine_v1beta_generated_completion_service_purge_suggestion_deny_list_entries_sync.py" }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.discoveryengine_v1beta.ConversationalSearchServiceAsyncClient", + "shortName": "ConversationalSearchServiceAsyncClient" + }, + "fullName": "google.cloud.discoveryengine_v1beta.ConversationalSearchServiceAsyncClient.answer_query", + "method": { + "fullName": "google.cloud.discoveryengine.v1beta.ConversationalSearchService.AnswerQuery", + "service": { + "fullName": "google.cloud.discoveryengine.v1beta.ConversationalSearchService", + "shortName": "ConversationalSearchService" + }, + "shortName": "AnswerQuery" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.discoveryengine_v1beta.types.AnswerQueryRequest" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.cloud.discoveryengine_v1beta.types.AnswerQueryResponse", + "shortName": "answer_query" + }, + "description": "Sample for AnswerQuery", + "file": "discoveryengine_v1beta_generated_conversational_search_service_answer_query_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "discoveryengine_v1beta_generated_ConversationalSearchService_AnswerQuery_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": "discoveryengine_v1beta_generated_conversational_search_service_answer_query_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.discoveryengine_v1beta.ConversationalSearchServiceClient", + "shortName": "ConversationalSearchServiceClient" + }, + "fullName": "google.cloud.discoveryengine_v1beta.ConversationalSearchServiceClient.answer_query", + "method": { + "fullName": "google.cloud.discoveryengine.v1beta.ConversationalSearchService.AnswerQuery", + "service": { + "fullName": "google.cloud.discoveryengine.v1beta.ConversationalSearchService", + "shortName": "ConversationalSearchService" + }, + "shortName": "AnswerQuery" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.discoveryengine_v1beta.types.AnswerQueryRequest" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "resultType": "google.cloud.discoveryengine_v1beta.types.AnswerQueryResponse", + "shortName": "answer_query" + }, + "description": "Sample for AnswerQuery", + "file": "discoveryengine_v1beta_generated_conversational_search_service_answer_query_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "discoveryengine_v1beta_generated_ConversationalSearchService_AnswerQuery_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": "discoveryengine_v1beta_generated_conversational_search_service_answer_query_sync.py" + }, { "canonical": true, "clientMethod": { @@ -816,24 +969,28 @@ "fullName": "google.cloud.discoveryengine_v1beta.ConversationalSearchServiceAsyncClient", "shortName": "ConversationalSearchServiceAsyncClient" }, - "fullName": "google.cloud.discoveryengine_v1beta.ConversationalSearchServiceAsyncClient.delete_conversation", + "fullName": "google.cloud.discoveryengine_v1beta.ConversationalSearchServiceAsyncClient.create_session", "method": { - "fullName": "google.cloud.discoveryengine.v1beta.ConversationalSearchService.DeleteConversation", + "fullName": "google.cloud.discoveryengine.v1beta.ConversationalSearchService.CreateSession", "service": { "fullName": "google.cloud.discoveryengine.v1beta.ConversationalSearchService", "shortName": "ConversationalSearchService" }, - "shortName": "DeleteConversation" + "shortName": "CreateSession" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1beta.types.DeleteConversationRequest" + "type": "google.cloud.discoveryengine_v1beta.types.CreateSessionRequest" }, { - "name": "name", + "name": "parent", "type": "str" }, + { + "name": "session", + "type": "google.cloud.discoveryengine_v1beta.types.Session" + }, { "name": "retry", "type": "google.api_core.retry.Retry" @@ -847,21 +1004,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "shortName": "delete_conversation" + "resultType": "google.cloud.discoveryengine_v1beta.types.Session", + "shortName": "create_session" }, - "description": "Sample for DeleteConversation", - "file": "discoveryengine_v1beta_generated_conversational_search_service_delete_conversation_async.py", + "description": "Sample for CreateSession", + "file": "discoveryengine_v1beta_generated_conversational_search_service_create_session_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1beta_generated_ConversationalSearchService_DeleteConversation_async", + "regionTag": "discoveryengine_v1beta_generated_ConversationalSearchService_CreateSession_async", "segments": [ { - "end": 49, + "end": 51, "start": 27, "type": "FULL" }, { - "end": 49, + "end": 51, "start": 27, "type": "SHORT" }, @@ -876,15 +1034,17 @@ "type": "REQUEST_INITIALIZATION" }, { + "end": 48, "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 50, + "end": 52, + "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1beta_generated_conversational_search_service_delete_conversation_async.py" + "title": "discoveryengine_v1beta_generated_conversational_search_service_create_session_async.py" }, { "canonical": true, @@ -893,24 +1053,28 @@ "fullName": "google.cloud.discoveryengine_v1beta.ConversationalSearchServiceClient", "shortName": "ConversationalSearchServiceClient" }, - "fullName": "google.cloud.discoveryengine_v1beta.ConversationalSearchServiceClient.delete_conversation", + "fullName": "google.cloud.discoveryengine_v1beta.ConversationalSearchServiceClient.create_session", "method": { - "fullName": "google.cloud.discoveryengine.v1beta.ConversationalSearchService.DeleteConversation", + "fullName": "google.cloud.discoveryengine.v1beta.ConversationalSearchService.CreateSession", "service": { "fullName": "google.cloud.discoveryengine.v1beta.ConversationalSearchService", "shortName": "ConversationalSearchService" }, - "shortName": "DeleteConversation" + "shortName": "CreateSession" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1beta.types.DeleteConversationRequest" + "type": "google.cloud.discoveryengine_v1beta.types.CreateSessionRequest" }, { - "name": "name", + "name": "parent", "type": "str" }, + { + "name": "session", + "type": "google.cloud.discoveryengine_v1beta.types.Session" + }, { "name": "retry", "type": "google.api_core.retry.Retry" @@ -924,21 +1088,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "shortName": "delete_conversation" + "resultType": "google.cloud.discoveryengine_v1beta.types.Session", + "shortName": "create_session" }, - "description": "Sample for DeleteConversation", - "file": "discoveryengine_v1beta_generated_conversational_search_service_delete_conversation_sync.py", + "description": "Sample for CreateSession", + "file": "discoveryengine_v1beta_generated_conversational_search_service_create_session_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1beta_generated_ConversationalSearchService_DeleteConversation_sync", + "regionTag": "discoveryengine_v1beta_generated_ConversationalSearchService_CreateSession_sync", "segments": [ { - "end": 49, + "end": 51, "start": 27, "type": "FULL" }, { - "end": 49, + "end": 51, "start": 27, "type": "SHORT" }, @@ -953,15 +1118,17 @@ "type": "REQUEST_INITIALIZATION" }, { + "end": 48, "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 50, + "end": 52, + "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1beta_generated_conversational_search_service_delete_conversation_sync.py" + "title": "discoveryengine_v1beta_generated_conversational_search_service_create_session_sync.py" }, { "canonical": true, @@ -971,19 +1138,19 @@ "fullName": "google.cloud.discoveryengine_v1beta.ConversationalSearchServiceAsyncClient", "shortName": "ConversationalSearchServiceAsyncClient" }, - "fullName": "google.cloud.discoveryengine_v1beta.ConversationalSearchServiceAsyncClient.get_conversation", + "fullName": "google.cloud.discoveryengine_v1beta.ConversationalSearchServiceAsyncClient.delete_conversation", "method": { - "fullName": "google.cloud.discoveryengine.v1beta.ConversationalSearchService.GetConversation", + "fullName": "google.cloud.discoveryengine.v1beta.ConversationalSearchService.DeleteConversation", "service": { "fullName": "google.cloud.discoveryengine.v1beta.ConversationalSearchService", "shortName": "ConversationalSearchService" }, - "shortName": "GetConversation" + "shortName": "DeleteConversation" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1beta.types.GetConversationRequest" + "type": "google.cloud.discoveryengine_v1beta.types.DeleteConversationRequest" }, { "name": "name", @@ -1002,22 +1169,21 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1beta.types.Conversation", - "shortName": "get_conversation" + "shortName": "delete_conversation" }, - "description": "Sample for GetConversation", - "file": "discoveryengine_v1beta_generated_conversational_search_service_get_conversation_async.py", + "description": "Sample for DeleteConversation", + "file": "discoveryengine_v1beta_generated_conversational_search_service_delete_conversation_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1beta_generated_ConversationalSearchService_GetConversation_async", + "regionTag": "discoveryengine_v1beta_generated_ConversationalSearchService_DeleteConversation_async", "segments": [ { - "end": 51, + "end": 49, "start": 27, "type": "FULL" }, { - "end": 51, + "end": 49, "start": 27, "type": "SHORT" }, @@ -1032,17 +1198,15 @@ "type": "REQUEST_INITIALIZATION" }, { - "end": 48, "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 52, - "start": 49, + "end": 50, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1beta_generated_conversational_search_service_get_conversation_async.py" + "title": "discoveryengine_v1beta_generated_conversational_search_service_delete_conversation_async.py" }, { "canonical": true, @@ -1051,19 +1215,19 @@ "fullName": "google.cloud.discoveryengine_v1beta.ConversationalSearchServiceClient", "shortName": "ConversationalSearchServiceClient" }, - "fullName": "google.cloud.discoveryengine_v1beta.ConversationalSearchServiceClient.get_conversation", + "fullName": "google.cloud.discoveryengine_v1beta.ConversationalSearchServiceClient.delete_conversation", "method": { - "fullName": "google.cloud.discoveryengine.v1beta.ConversationalSearchService.GetConversation", + "fullName": "google.cloud.discoveryengine.v1beta.ConversationalSearchService.DeleteConversation", "service": { "fullName": "google.cloud.discoveryengine.v1beta.ConversationalSearchService", "shortName": "ConversationalSearchService" }, - "shortName": "GetConversation" + "shortName": "DeleteConversation" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1beta.types.GetConversationRequest" + "type": "google.cloud.discoveryengine_v1beta.types.DeleteConversationRequest" }, { "name": "name", @@ -1082,22 +1246,21 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1beta.types.Conversation", - "shortName": "get_conversation" + "shortName": "delete_conversation" }, - "description": "Sample for GetConversation", - "file": "discoveryengine_v1beta_generated_conversational_search_service_get_conversation_sync.py", + "description": "Sample for DeleteConversation", + "file": "discoveryengine_v1beta_generated_conversational_search_service_delete_conversation_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1beta_generated_ConversationalSearchService_GetConversation_sync", + "regionTag": "discoveryengine_v1beta_generated_ConversationalSearchService_DeleteConversation_sync", "segments": [ { - "end": 51, + "end": 49, "start": 27, "type": "FULL" }, { - "end": 51, + "end": 49, "start": 27, "type": "SHORT" }, @@ -1112,17 +1275,15 @@ "type": "REQUEST_INITIALIZATION" }, { - "end": 48, "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 52, - "start": 49, + "end": 50, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1beta_generated_conversational_search_service_get_conversation_sync.py" + "title": "discoveryengine_v1beta_generated_conversational_search_service_delete_conversation_sync.py" }, { "canonical": true, @@ -1132,22 +1293,22 @@ "fullName": "google.cloud.discoveryengine_v1beta.ConversationalSearchServiceAsyncClient", "shortName": "ConversationalSearchServiceAsyncClient" }, - "fullName": "google.cloud.discoveryengine_v1beta.ConversationalSearchServiceAsyncClient.list_conversations", + "fullName": "google.cloud.discoveryengine_v1beta.ConversationalSearchServiceAsyncClient.delete_session", "method": { - "fullName": "google.cloud.discoveryengine.v1beta.ConversationalSearchService.ListConversations", + "fullName": "google.cloud.discoveryengine.v1beta.ConversationalSearchService.DeleteSession", "service": { "fullName": "google.cloud.discoveryengine.v1beta.ConversationalSearchService", "shortName": "ConversationalSearchService" }, - "shortName": "ListConversations" + "shortName": "DeleteSession" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1beta.types.ListConversationsRequest" + "type": "google.cloud.discoveryengine_v1beta.types.DeleteSessionRequest" }, { - "name": "parent", + "name": "name", "type": "str" }, { @@ -1163,22 +1324,21 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1beta.services.conversational_search_service.pagers.ListConversationsAsyncPager", - "shortName": "list_conversations" + "shortName": "delete_session" }, - "description": "Sample for ListConversations", - "file": "discoveryengine_v1beta_generated_conversational_search_service_list_conversations_async.py", + "description": "Sample for DeleteSession", + "file": "discoveryengine_v1beta_generated_conversational_search_service_delete_session_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1beta_generated_ConversationalSearchService_ListConversations_async", + "regionTag": "discoveryengine_v1beta_generated_ConversationalSearchService_DeleteSession_async", "segments": [ { - "end": 52, + "end": 49, "start": 27, "type": "FULL" }, { - "end": 52, + "end": 49, "start": 27, "type": "SHORT" }, @@ -1193,17 +1353,15 @@ "type": "REQUEST_INITIALIZATION" }, { - "end": 48, "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 53, - "start": 49, + "end": 50, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1beta_generated_conversational_search_service_list_conversations_async.py" + "title": "discoveryengine_v1beta_generated_conversational_search_service_delete_session_async.py" }, { "canonical": true, @@ -1212,22 +1370,22 @@ "fullName": "google.cloud.discoveryengine_v1beta.ConversationalSearchServiceClient", "shortName": "ConversationalSearchServiceClient" }, - "fullName": "google.cloud.discoveryengine_v1beta.ConversationalSearchServiceClient.list_conversations", + "fullName": "google.cloud.discoveryengine_v1beta.ConversationalSearchServiceClient.delete_session", "method": { - "fullName": "google.cloud.discoveryengine.v1beta.ConversationalSearchService.ListConversations", + "fullName": "google.cloud.discoveryengine.v1beta.ConversationalSearchService.DeleteSession", "service": { "fullName": "google.cloud.discoveryengine.v1beta.ConversationalSearchService", "shortName": "ConversationalSearchService" }, - "shortName": "ListConversations" + "shortName": "DeleteSession" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1beta.types.ListConversationsRequest" + "type": "google.cloud.discoveryengine_v1beta.types.DeleteSessionRequest" }, { - "name": "parent", + "name": "name", "type": "str" }, { @@ -1243,22 +1401,21 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1beta.services.conversational_search_service.pagers.ListConversationsPager", - "shortName": "list_conversations" + "shortName": "delete_session" }, - "description": "Sample for ListConversations", - "file": "discoveryengine_v1beta_generated_conversational_search_service_list_conversations_sync.py", + "description": "Sample for DeleteSession", + "file": "discoveryengine_v1beta_generated_conversational_search_service_delete_session_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1beta_generated_ConversationalSearchService_ListConversations_sync", + "regionTag": "discoveryengine_v1beta_generated_ConversationalSearchService_DeleteSession_sync", "segments": [ { - "end": 52, + "end": 49, "start": 27, "type": "FULL" }, { - "end": 52, + "end": 49, "start": 27, "type": "SHORT" }, @@ -1273,17 +1430,15 @@ "type": "REQUEST_INITIALIZATION" }, { - "end": 48, "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 53, - "start": 49, + "end": 50, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1beta_generated_conversational_search_service_list_conversations_sync.py" + "title": "discoveryengine_v1beta_generated_conversational_search_service_delete_session_sync.py" }, { "canonical": true, @@ -1293,27 +1448,23 @@ "fullName": "google.cloud.discoveryengine_v1beta.ConversationalSearchServiceAsyncClient", "shortName": "ConversationalSearchServiceAsyncClient" }, - "fullName": "google.cloud.discoveryengine_v1beta.ConversationalSearchServiceAsyncClient.update_conversation", + "fullName": "google.cloud.discoveryengine_v1beta.ConversationalSearchServiceAsyncClient.get_answer", "method": { - "fullName": "google.cloud.discoveryengine.v1beta.ConversationalSearchService.UpdateConversation", + "fullName": "google.cloud.discoveryengine.v1beta.ConversationalSearchService.GetAnswer", "service": { "fullName": "google.cloud.discoveryengine.v1beta.ConversationalSearchService", "shortName": "ConversationalSearchService" }, - "shortName": "UpdateConversation" + "shortName": "GetAnswer" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1beta.types.UpdateConversationRequest" - }, - { - "name": "conversation", - "type": "google.cloud.discoveryengine_v1beta.types.Conversation" + "type": "google.cloud.discoveryengine_v1beta.types.GetAnswerRequest" }, { - "name": "update_mask", - "type": "google.protobuf.field_mask_pb2.FieldMask" + "name": "name", + "type": "str" }, { "name": "retry", @@ -1328,22 +1479,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1beta.types.Conversation", - "shortName": "update_conversation" + "resultType": "google.cloud.discoveryengine_v1beta.types.Answer", + "shortName": "get_answer" }, - "description": "Sample for UpdateConversation", - "file": "discoveryengine_v1beta_generated_conversational_search_service_update_conversation_async.py", + "description": "Sample for GetAnswer", + "file": "discoveryengine_v1beta_generated_conversational_search_service_get_answer_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1beta_generated_ConversationalSearchService_UpdateConversation_async", + "regionTag": "discoveryengine_v1beta_generated_ConversationalSearchService_GetAnswer_async", "segments": [ { - "end": 50, + "end": 51, "start": 27, "type": "FULL" }, { - "end": 50, + "end": 51, "start": 27, "type": "SHORT" }, @@ -1353,22 +1504,22 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 44, + "end": 45, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 47, - "start": 45, + "end": 48, + "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 51, - "start": 48, + "end": 52, + "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1beta_generated_conversational_search_service_update_conversation_async.py" + "title": "discoveryengine_v1beta_generated_conversational_search_service_get_answer_async.py" }, { "canonical": true, @@ -1377,27 +1528,23 @@ "fullName": "google.cloud.discoveryengine_v1beta.ConversationalSearchServiceClient", "shortName": "ConversationalSearchServiceClient" }, - "fullName": "google.cloud.discoveryengine_v1beta.ConversationalSearchServiceClient.update_conversation", + "fullName": "google.cloud.discoveryengine_v1beta.ConversationalSearchServiceClient.get_answer", "method": { - "fullName": "google.cloud.discoveryengine.v1beta.ConversationalSearchService.UpdateConversation", + "fullName": "google.cloud.discoveryengine.v1beta.ConversationalSearchService.GetAnswer", "service": { "fullName": "google.cloud.discoveryengine.v1beta.ConversationalSearchService", "shortName": "ConversationalSearchService" }, - "shortName": "UpdateConversation" + "shortName": "GetAnswer" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1beta.types.UpdateConversationRequest" - }, - { - "name": "conversation", - "type": "google.cloud.discoveryengine_v1beta.types.Conversation" + "type": "google.cloud.discoveryengine_v1beta.types.GetAnswerRequest" }, { - "name": "update_mask", - "type": "google.protobuf.field_mask_pb2.FieldMask" + "name": "name", + "type": "str" }, { "name": "retry", @@ -1412,22 +1559,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1beta.types.Conversation", - "shortName": "update_conversation" + "resultType": "google.cloud.discoveryengine_v1beta.types.Answer", + "shortName": "get_answer" }, - "description": "Sample for UpdateConversation", - "file": "discoveryengine_v1beta_generated_conversational_search_service_update_conversation_sync.py", + "description": "Sample for GetAnswer", + "file": "discoveryengine_v1beta_generated_conversational_search_service_get_answer_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1beta_generated_ConversationalSearchService_UpdateConversation_sync", + "regionTag": "discoveryengine_v1beta_generated_ConversationalSearchService_GetAnswer_sync", "segments": [ { - "end": 50, + "end": 51, "start": 27, "type": "FULL" }, { - "end": 50, + "end": 51, "start": 27, "type": "SHORT" }, @@ -1437,55 +1584,47 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 44, + "end": 45, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 47, - "start": 45, + "end": 48, + "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 51, - "start": 48, + "end": 52, + "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1beta_generated_conversational_search_service_update_conversation_sync.py" + "title": "discoveryengine_v1beta_generated_conversational_search_service_get_answer_sync.py" }, { "canonical": true, "clientMethod": { "async": true, "client": { - "fullName": "google.cloud.discoveryengine_v1beta.DataStoreServiceAsyncClient", - "shortName": "DataStoreServiceAsyncClient" + "fullName": "google.cloud.discoveryengine_v1beta.ConversationalSearchServiceAsyncClient", + "shortName": "ConversationalSearchServiceAsyncClient" }, - "fullName": "google.cloud.discoveryengine_v1beta.DataStoreServiceAsyncClient.create_data_store", + "fullName": "google.cloud.discoveryengine_v1beta.ConversationalSearchServiceAsyncClient.get_conversation", "method": { - "fullName": "google.cloud.discoveryengine.v1beta.DataStoreService.CreateDataStore", + "fullName": "google.cloud.discoveryengine.v1beta.ConversationalSearchService.GetConversation", "service": { - "fullName": "google.cloud.discoveryengine.v1beta.DataStoreService", - "shortName": "DataStoreService" + "fullName": "google.cloud.discoveryengine.v1beta.ConversationalSearchService", + "shortName": "ConversationalSearchService" }, - "shortName": "CreateDataStore" + "shortName": "GetConversation" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1beta.types.CreateDataStoreRequest" - }, - { - "name": "parent", - "type": "str" - }, - { - "name": "data_store", - "type": "google.cloud.discoveryengine_v1beta.types.DataStore" + "type": "google.cloud.discoveryengine_v1beta.types.GetConversationRequest" }, { - "name": "data_store_id", + "name": "name", "type": "str" }, { @@ -1501,22 +1640,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.api_core.operation_async.AsyncOperation", - "shortName": "create_data_store" + "resultType": "google.cloud.discoveryengine_v1beta.types.Conversation", + "shortName": "get_conversation" }, - "description": "Sample for CreateDataStore", - "file": "discoveryengine_v1beta_generated_data_store_service_create_data_store_async.py", + "description": "Sample for GetConversation", + "file": "discoveryengine_v1beta_generated_conversational_search_service_get_conversation_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1beta_generated_DataStoreService_CreateDataStore_async", + "regionTag": "discoveryengine_v1beta_generated_ConversationalSearchService_GetConversation_async", "segments": [ { - "end": 60, + "end": 51, "start": 27, "type": "FULL" }, { - "end": 60, + "end": 51, "start": 27, "type": "SHORT" }, @@ -1526,54 +1665,46 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 50, + "end": 45, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 57, - "start": 51, + "end": 48, + "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 61, - "start": 58, + "end": 52, + "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1beta_generated_data_store_service_create_data_store_async.py" + "title": "discoveryengine_v1beta_generated_conversational_search_service_get_conversation_async.py" }, { "canonical": true, "clientMethod": { "client": { - "fullName": "google.cloud.discoveryengine_v1beta.DataStoreServiceClient", - "shortName": "DataStoreServiceClient" + "fullName": "google.cloud.discoveryengine_v1beta.ConversationalSearchServiceClient", + "shortName": "ConversationalSearchServiceClient" }, - "fullName": "google.cloud.discoveryengine_v1beta.DataStoreServiceClient.create_data_store", + "fullName": "google.cloud.discoveryengine_v1beta.ConversationalSearchServiceClient.get_conversation", "method": { - "fullName": "google.cloud.discoveryengine.v1beta.DataStoreService.CreateDataStore", + "fullName": "google.cloud.discoveryengine.v1beta.ConversationalSearchService.GetConversation", "service": { - "fullName": "google.cloud.discoveryengine.v1beta.DataStoreService", - "shortName": "DataStoreService" + "fullName": "google.cloud.discoveryengine.v1beta.ConversationalSearchService", + "shortName": "ConversationalSearchService" }, - "shortName": "CreateDataStore" + "shortName": "GetConversation" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1beta.types.CreateDataStoreRequest" - }, - { - "name": "parent", - "type": "str" - }, - { - "name": "data_store", - "type": "google.cloud.discoveryengine_v1beta.types.DataStore" + "type": "google.cloud.discoveryengine_v1beta.types.GetConversationRequest" }, { - "name": "data_store_id", + "name": "name", "type": "str" }, { @@ -1589,22 +1720,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.api_core.operation.Operation", - "shortName": "create_data_store" + "resultType": "google.cloud.discoveryengine_v1beta.types.Conversation", + "shortName": "get_conversation" }, - "description": "Sample for CreateDataStore", - "file": "discoveryengine_v1beta_generated_data_store_service_create_data_store_sync.py", + "description": "Sample for GetConversation", + "file": "discoveryengine_v1beta_generated_conversational_search_service_get_conversation_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1beta_generated_DataStoreService_CreateDataStore_sync", + "regionTag": "discoveryengine_v1beta_generated_ConversationalSearchService_GetConversation_sync", "segments": [ { - "end": 60, + "end": 51, "start": 27, "type": "FULL" }, { - "end": 60, + "end": 51, "start": 27, "type": "SHORT" }, @@ -1614,44 +1745,44 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 50, + "end": 45, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 57, - "start": 51, + "end": 48, + "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 61, - "start": 58, + "end": 52, + "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1beta_generated_data_store_service_create_data_store_sync.py" + "title": "discoveryengine_v1beta_generated_conversational_search_service_get_conversation_sync.py" }, { "canonical": true, "clientMethod": { "async": true, "client": { - "fullName": "google.cloud.discoveryengine_v1beta.DataStoreServiceAsyncClient", - "shortName": "DataStoreServiceAsyncClient" + "fullName": "google.cloud.discoveryengine_v1beta.ConversationalSearchServiceAsyncClient", + "shortName": "ConversationalSearchServiceAsyncClient" }, - "fullName": "google.cloud.discoveryengine_v1beta.DataStoreServiceAsyncClient.delete_data_store", + "fullName": "google.cloud.discoveryengine_v1beta.ConversationalSearchServiceAsyncClient.get_session", "method": { - "fullName": "google.cloud.discoveryengine.v1beta.DataStoreService.DeleteDataStore", + "fullName": "google.cloud.discoveryengine.v1beta.ConversationalSearchService.GetSession", "service": { - "fullName": "google.cloud.discoveryengine.v1beta.DataStoreService", - "shortName": "DataStoreService" + "fullName": "google.cloud.discoveryengine.v1beta.ConversationalSearchService", + "shortName": "ConversationalSearchService" }, - "shortName": "DeleteDataStore" + "shortName": "GetSession" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1beta.types.DeleteDataStoreRequest" + "type": "google.cloud.discoveryengine_v1beta.types.GetSessionRequest" }, { "name": "name", @@ -1670,22 +1801,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.api_core.operation_async.AsyncOperation", - "shortName": "delete_data_store" + "resultType": "google.cloud.discoveryengine_v1beta.types.Session", + "shortName": "get_session" }, - "description": "Sample for DeleteDataStore", - "file": "discoveryengine_v1beta_generated_data_store_service_delete_data_store_async.py", + "description": "Sample for GetSession", + "file": "discoveryengine_v1beta_generated_conversational_search_service_get_session_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1beta_generated_DataStoreService_DeleteDataStore_async", + "regionTag": "discoveryengine_v1beta_generated_ConversationalSearchService_GetSession_async", "segments": [ { - "end": 55, + "end": 51, "start": 27, "type": "FULL" }, { - "end": 55, + "end": 51, "start": 27, "type": "SHORT" }, @@ -1700,38 +1831,38 @@ "type": "REQUEST_INITIALIZATION" }, { - "end": 52, + "end": 48, "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 56, - "start": 53, + "end": 52, + "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1beta_generated_data_store_service_delete_data_store_async.py" + "title": "discoveryengine_v1beta_generated_conversational_search_service_get_session_async.py" }, { "canonical": true, "clientMethod": { "client": { - "fullName": "google.cloud.discoveryengine_v1beta.DataStoreServiceClient", - "shortName": "DataStoreServiceClient" + "fullName": "google.cloud.discoveryengine_v1beta.ConversationalSearchServiceClient", + "shortName": "ConversationalSearchServiceClient" }, - "fullName": "google.cloud.discoveryengine_v1beta.DataStoreServiceClient.delete_data_store", + "fullName": "google.cloud.discoveryengine_v1beta.ConversationalSearchServiceClient.get_session", "method": { - "fullName": "google.cloud.discoveryengine.v1beta.DataStoreService.DeleteDataStore", + "fullName": "google.cloud.discoveryengine.v1beta.ConversationalSearchService.GetSession", "service": { - "fullName": "google.cloud.discoveryengine.v1beta.DataStoreService", - "shortName": "DataStoreService" + "fullName": "google.cloud.discoveryengine.v1beta.ConversationalSearchService", + "shortName": "ConversationalSearchService" }, - "shortName": "DeleteDataStore" + "shortName": "GetSession" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1beta.types.DeleteDataStoreRequest" + "type": "google.cloud.discoveryengine_v1beta.types.GetSessionRequest" }, { "name": "name", @@ -1750,22 +1881,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.api_core.operation.Operation", - "shortName": "delete_data_store" + "resultType": "google.cloud.discoveryengine_v1beta.types.Session", + "shortName": "get_session" }, - "description": "Sample for DeleteDataStore", - "file": "discoveryengine_v1beta_generated_data_store_service_delete_data_store_sync.py", + "description": "Sample for GetSession", + "file": "discoveryengine_v1beta_generated_conversational_search_service_get_session_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1beta_generated_DataStoreService_DeleteDataStore_sync", + "regionTag": "discoveryengine_v1beta_generated_ConversationalSearchService_GetSession_sync", "segments": [ { - "end": 55, + "end": 51, "start": 27, "type": "FULL" }, { - "end": 55, + "end": 51, "start": 27, "type": "SHORT" }, @@ -1780,42 +1911,42 @@ "type": "REQUEST_INITIALIZATION" }, { - "end": 52, + "end": 48, "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 56, - "start": 53, + "end": 52, + "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1beta_generated_data_store_service_delete_data_store_sync.py" + "title": "discoveryengine_v1beta_generated_conversational_search_service_get_session_sync.py" }, { "canonical": true, "clientMethod": { "async": true, "client": { - "fullName": "google.cloud.discoveryengine_v1beta.DataStoreServiceAsyncClient", - "shortName": "DataStoreServiceAsyncClient" + "fullName": "google.cloud.discoveryengine_v1beta.ConversationalSearchServiceAsyncClient", + "shortName": "ConversationalSearchServiceAsyncClient" }, - "fullName": "google.cloud.discoveryengine_v1beta.DataStoreServiceAsyncClient.get_data_store", + "fullName": "google.cloud.discoveryengine_v1beta.ConversationalSearchServiceAsyncClient.list_conversations", "method": { - "fullName": "google.cloud.discoveryengine.v1beta.DataStoreService.GetDataStore", + "fullName": "google.cloud.discoveryengine.v1beta.ConversationalSearchService.ListConversations", "service": { - "fullName": "google.cloud.discoveryengine.v1beta.DataStoreService", - "shortName": "DataStoreService" + "fullName": "google.cloud.discoveryengine.v1beta.ConversationalSearchService", + "shortName": "ConversationalSearchService" }, - "shortName": "GetDataStore" + "shortName": "ListConversations" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1beta.types.GetDataStoreRequest" + "type": "google.cloud.discoveryengine_v1beta.types.ListConversationsRequest" }, { - "name": "name", + "name": "parent", "type": "str" }, { @@ -1831,22 +1962,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1beta.types.DataStore", - "shortName": "get_data_store" + "resultType": "google.cloud.discoveryengine_v1beta.services.conversational_search_service.pagers.ListConversationsAsyncPager", + "shortName": "list_conversations" }, - "description": "Sample for GetDataStore", - "file": "discoveryengine_v1beta_generated_data_store_service_get_data_store_async.py", + "description": "Sample for ListConversations", + "file": "discoveryengine_v1beta_generated_conversational_search_service_list_conversations_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1beta_generated_DataStoreService_GetDataStore_async", + "regionTag": "discoveryengine_v1beta_generated_ConversationalSearchService_ListConversations_async", "segments": [ { - "end": 51, + "end": 52, "start": 27, "type": "FULL" }, { - "end": 51, + "end": 52, "start": 27, "type": "SHORT" }, @@ -1866,36 +1997,36 @@ "type": "REQUEST_EXECUTION" }, { - "end": 52, + "end": 53, "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1beta_generated_data_store_service_get_data_store_async.py" + "title": "discoveryengine_v1beta_generated_conversational_search_service_list_conversations_async.py" }, { "canonical": true, "clientMethod": { "client": { - "fullName": "google.cloud.discoveryengine_v1beta.DataStoreServiceClient", - "shortName": "DataStoreServiceClient" + "fullName": "google.cloud.discoveryengine_v1beta.ConversationalSearchServiceClient", + "shortName": "ConversationalSearchServiceClient" }, - "fullName": "google.cloud.discoveryengine_v1beta.DataStoreServiceClient.get_data_store", + "fullName": "google.cloud.discoveryengine_v1beta.ConversationalSearchServiceClient.list_conversations", "method": { - "fullName": "google.cloud.discoveryengine.v1beta.DataStoreService.GetDataStore", + "fullName": "google.cloud.discoveryengine.v1beta.ConversationalSearchService.ListConversations", "service": { - "fullName": "google.cloud.discoveryengine.v1beta.DataStoreService", - "shortName": "DataStoreService" + "fullName": "google.cloud.discoveryengine.v1beta.ConversationalSearchService", + "shortName": "ConversationalSearchService" }, - "shortName": "GetDataStore" + "shortName": "ListConversations" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1beta.types.GetDataStoreRequest" + "type": "google.cloud.discoveryengine_v1beta.types.ListConversationsRequest" }, { - "name": "name", + "name": "parent", "type": "str" }, { @@ -1911,22 +2042,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1beta.types.DataStore", - "shortName": "get_data_store" + "resultType": "google.cloud.discoveryengine_v1beta.services.conversational_search_service.pagers.ListConversationsPager", + "shortName": "list_conversations" }, - "description": "Sample for GetDataStore", - "file": "discoveryengine_v1beta_generated_data_store_service_get_data_store_sync.py", + "description": "Sample for ListConversations", + "file": "discoveryengine_v1beta_generated_conversational_search_service_list_conversations_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1beta_generated_DataStoreService_GetDataStore_sync", + "regionTag": "discoveryengine_v1beta_generated_ConversationalSearchService_ListConversations_sync", "segments": [ { - "end": 51, + "end": 52, "start": 27, "type": "FULL" }, { - "end": 51, + "end": 52, "start": 27, "type": "SHORT" }, @@ -1946,34 +2077,34 @@ "type": "REQUEST_EXECUTION" }, { - "end": 52, + "end": 53, "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1beta_generated_data_store_service_get_data_store_sync.py" + "title": "discoveryengine_v1beta_generated_conversational_search_service_list_conversations_sync.py" }, { "canonical": true, "clientMethod": { "async": true, "client": { - "fullName": "google.cloud.discoveryengine_v1beta.DataStoreServiceAsyncClient", - "shortName": "DataStoreServiceAsyncClient" + "fullName": "google.cloud.discoveryengine_v1beta.ConversationalSearchServiceAsyncClient", + "shortName": "ConversationalSearchServiceAsyncClient" }, - "fullName": "google.cloud.discoveryengine_v1beta.DataStoreServiceAsyncClient.list_data_stores", + "fullName": "google.cloud.discoveryengine_v1beta.ConversationalSearchServiceAsyncClient.list_sessions", "method": { - "fullName": "google.cloud.discoveryengine.v1beta.DataStoreService.ListDataStores", + "fullName": "google.cloud.discoveryengine.v1beta.ConversationalSearchService.ListSessions", "service": { - "fullName": "google.cloud.discoveryengine.v1beta.DataStoreService", - "shortName": "DataStoreService" + "fullName": "google.cloud.discoveryengine.v1beta.ConversationalSearchService", + "shortName": "ConversationalSearchService" }, - "shortName": "ListDataStores" + "shortName": "ListSessions" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1beta.types.ListDataStoresRequest" + "type": "google.cloud.discoveryengine_v1beta.types.ListSessionsRequest" }, { "name": "parent", @@ -1992,14 +2123,14 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1beta.services.data_store_service.pagers.ListDataStoresAsyncPager", - "shortName": "list_data_stores" + "resultType": "google.cloud.discoveryengine_v1beta.services.conversational_search_service.pagers.ListSessionsAsyncPager", + "shortName": "list_sessions" }, - "description": "Sample for ListDataStores", - "file": "discoveryengine_v1beta_generated_data_store_service_list_data_stores_async.py", + "description": "Sample for ListSessions", + "file": "discoveryengine_v1beta_generated_conversational_search_service_list_sessions_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1beta_generated_DataStoreService_ListDataStores_async", + "regionTag": "discoveryengine_v1beta_generated_ConversationalSearchService_ListSessions_async", "segments": [ { "end": 52, @@ -2032,28 +2163,28 @@ "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1beta_generated_data_store_service_list_data_stores_async.py" + "title": "discoveryengine_v1beta_generated_conversational_search_service_list_sessions_async.py" }, { "canonical": true, "clientMethod": { "client": { - "fullName": "google.cloud.discoveryengine_v1beta.DataStoreServiceClient", - "shortName": "DataStoreServiceClient" + "fullName": "google.cloud.discoveryengine_v1beta.ConversationalSearchServiceClient", + "shortName": "ConversationalSearchServiceClient" }, - "fullName": "google.cloud.discoveryengine_v1beta.DataStoreServiceClient.list_data_stores", + "fullName": "google.cloud.discoveryengine_v1beta.ConversationalSearchServiceClient.list_sessions", "method": { - "fullName": "google.cloud.discoveryengine.v1beta.DataStoreService.ListDataStores", + "fullName": "google.cloud.discoveryengine.v1beta.ConversationalSearchService.ListSessions", "service": { - "fullName": "google.cloud.discoveryengine.v1beta.DataStoreService", - "shortName": "DataStoreService" + "fullName": "google.cloud.discoveryengine.v1beta.ConversationalSearchService", + "shortName": "ConversationalSearchService" }, - "shortName": "ListDataStores" + "shortName": "ListSessions" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1beta.types.ListDataStoresRequest" + "type": "google.cloud.discoveryengine_v1beta.types.ListSessionsRequest" }, { "name": "parent", @@ -2072,14 +2203,14 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1beta.services.data_store_service.pagers.ListDataStoresPager", - "shortName": "list_data_stores" + "resultType": "google.cloud.discoveryengine_v1beta.services.conversational_search_service.pagers.ListSessionsPager", + "shortName": "list_sessions" }, - "description": "Sample for ListDataStores", - "file": "discoveryengine_v1beta_generated_data_store_service_list_data_stores_sync.py", + "description": "Sample for ListSessions", + "file": "discoveryengine_v1beta_generated_conversational_search_service_list_sessions_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1beta_generated_DataStoreService_ListDataStores_sync", + "regionTag": "discoveryengine_v1beta_generated_ConversationalSearchService_ListSessions_sync", "segments": [ { "end": 52, @@ -2112,33 +2243,33 @@ "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1beta_generated_data_store_service_list_data_stores_sync.py" + "title": "discoveryengine_v1beta_generated_conversational_search_service_list_sessions_sync.py" }, { "canonical": true, "clientMethod": { "async": true, "client": { - "fullName": "google.cloud.discoveryengine_v1beta.DataStoreServiceAsyncClient", - "shortName": "DataStoreServiceAsyncClient" + "fullName": "google.cloud.discoveryengine_v1beta.ConversationalSearchServiceAsyncClient", + "shortName": "ConversationalSearchServiceAsyncClient" }, - "fullName": "google.cloud.discoveryengine_v1beta.DataStoreServiceAsyncClient.update_data_store", + "fullName": "google.cloud.discoveryengine_v1beta.ConversationalSearchServiceAsyncClient.update_conversation", "method": { - "fullName": "google.cloud.discoveryengine.v1beta.DataStoreService.UpdateDataStore", + "fullName": "google.cloud.discoveryengine.v1beta.ConversationalSearchService.UpdateConversation", "service": { - "fullName": "google.cloud.discoveryengine.v1beta.DataStoreService", - "shortName": "DataStoreService" + "fullName": "google.cloud.discoveryengine.v1beta.ConversationalSearchService", + "shortName": "ConversationalSearchService" }, - "shortName": "UpdateDataStore" + "shortName": "UpdateConversation" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1beta.types.UpdateDataStoreRequest" + "type": "google.cloud.discoveryengine_v1beta.types.UpdateConversationRequest" }, { - "name": "data_store", - "type": "google.cloud.discoveryengine_v1beta.types.DataStore" + "name": "conversation", + "type": "google.cloud.discoveryengine_v1beta.types.Conversation" }, { "name": "update_mask", @@ -2157,22 +2288,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1beta.types.DataStore", - "shortName": "update_data_store" + "resultType": "google.cloud.discoveryengine_v1beta.types.Conversation", + "shortName": "update_conversation" }, - "description": "Sample for UpdateDataStore", - "file": "discoveryengine_v1beta_generated_data_store_service_update_data_store_async.py", + "description": "Sample for UpdateConversation", + "file": "discoveryengine_v1beta_generated_conversational_search_service_update_conversation_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1beta_generated_DataStoreService_UpdateDataStore_async", + "regionTag": "discoveryengine_v1beta_generated_ConversationalSearchService_UpdateConversation_async", "segments": [ { - "end": 54, + "end": 50, "start": 27, "type": "FULL" }, { - "end": 54, + "end": 50, "start": 27, "type": "SHORT" }, @@ -2182,47 +2313,47 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 48, + "end": 44, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 51, - "start": 49, + "end": 47, + "start": 45, "type": "REQUEST_EXECUTION" }, { - "end": 55, - "start": 52, + "end": 51, + "start": 48, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1beta_generated_data_store_service_update_data_store_async.py" + "title": "discoveryengine_v1beta_generated_conversational_search_service_update_conversation_async.py" }, { "canonical": true, "clientMethod": { "client": { - "fullName": "google.cloud.discoveryengine_v1beta.DataStoreServiceClient", - "shortName": "DataStoreServiceClient" + "fullName": "google.cloud.discoveryengine_v1beta.ConversationalSearchServiceClient", + "shortName": "ConversationalSearchServiceClient" }, - "fullName": "google.cloud.discoveryengine_v1beta.DataStoreServiceClient.update_data_store", + "fullName": "google.cloud.discoveryengine_v1beta.ConversationalSearchServiceClient.update_conversation", "method": { - "fullName": "google.cloud.discoveryengine.v1beta.DataStoreService.UpdateDataStore", + "fullName": "google.cloud.discoveryengine.v1beta.ConversationalSearchService.UpdateConversation", "service": { - "fullName": "google.cloud.discoveryengine.v1beta.DataStoreService", - "shortName": "DataStoreService" + "fullName": "google.cloud.discoveryengine.v1beta.ConversationalSearchService", + "shortName": "ConversationalSearchService" }, - "shortName": "UpdateDataStore" + "shortName": "UpdateConversation" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1beta.types.UpdateDataStoreRequest" + "type": "google.cloud.discoveryengine_v1beta.types.UpdateConversationRequest" }, { - "name": "data_store", - "type": "google.cloud.discoveryengine_v1beta.types.DataStore" + "name": "conversation", + "type": "google.cloud.discoveryengine_v1beta.types.Conversation" }, { "name": "update_mask", @@ -2241,22 +2372,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1beta.types.DataStore", - "shortName": "update_data_store" + "resultType": "google.cloud.discoveryengine_v1beta.types.Conversation", + "shortName": "update_conversation" }, - "description": "Sample for UpdateDataStore", - "file": "discoveryengine_v1beta_generated_data_store_service_update_data_store_sync.py", + "description": "Sample for UpdateConversation", + "file": "discoveryengine_v1beta_generated_conversational_search_service_update_conversation_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1beta_generated_DataStoreService_UpdateDataStore_sync", + "regionTag": "discoveryengine_v1beta_generated_ConversationalSearchService_UpdateConversation_sync", "segments": [ { - "end": 54, + "end": 50, "start": 27, "type": "FULL" }, { - "end": 54, + "end": 50, "start": 27, "type": "SHORT" }, @@ -2266,56 +2397,52 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 48, + "end": 44, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 51, - "start": 49, + "end": 47, + "start": 45, "type": "REQUEST_EXECUTION" }, { - "end": 55, - "start": 52, + "end": 51, + "start": 48, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1beta_generated_data_store_service_update_data_store_sync.py" + "title": "discoveryengine_v1beta_generated_conversational_search_service_update_conversation_sync.py" }, { "canonical": true, "clientMethod": { "async": true, "client": { - "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceAsyncClient", - "shortName": "DocumentServiceAsyncClient" + "fullName": "google.cloud.discoveryengine_v1beta.ConversationalSearchServiceAsyncClient", + "shortName": "ConversationalSearchServiceAsyncClient" }, - "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceAsyncClient.create_document", + "fullName": "google.cloud.discoveryengine_v1beta.ConversationalSearchServiceAsyncClient.update_session", "method": { - "fullName": "google.cloud.discoveryengine.v1beta.DocumentService.CreateDocument", + "fullName": "google.cloud.discoveryengine.v1beta.ConversationalSearchService.UpdateSession", "service": { - "fullName": "google.cloud.discoveryengine.v1beta.DocumentService", - "shortName": "DocumentService" + "fullName": "google.cloud.discoveryengine.v1beta.ConversationalSearchService", + "shortName": "ConversationalSearchService" }, - "shortName": "CreateDocument" + "shortName": "UpdateSession" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1beta.types.CreateDocumentRequest" - }, - { - "name": "parent", - "type": "str" + "type": "google.cloud.discoveryengine_v1beta.types.UpdateSessionRequest" }, { - "name": "document", - "type": "google.cloud.discoveryengine_v1beta.types.Document" + "name": "session", + "type": "google.cloud.discoveryengine_v1beta.types.Session" }, { - "name": "document_id", - "type": "str" + "name": "update_mask", + "type": "google.protobuf.field_mask_pb2.FieldMask" }, { "name": "retry", @@ -2330,22 +2457,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1beta.types.Document", - "shortName": "create_document" + "resultType": "google.cloud.discoveryengine_v1beta.types.Session", + "shortName": "update_session" }, - "description": "Sample for CreateDocument", - "file": "discoveryengine_v1beta_generated_document_service_create_document_async.py", + "description": "Sample for UpdateSession", + "file": "discoveryengine_v1beta_generated_conversational_search_service_update_session_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1beta_generated_DocumentService_CreateDocument_async", + "regionTag": "discoveryengine_v1beta_generated_ConversationalSearchService_UpdateSession_async", "segments": [ { - "end": 52, + "end": 50, "start": 27, "type": "FULL" }, { - "end": 52, + "end": 50, "start": 27, "type": "SHORT" }, @@ -2355,55 +2482,51 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 46, + "end": 44, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 49, - "start": 47, + "end": 47, + "start": 45, "type": "REQUEST_EXECUTION" }, { - "end": 53, - "start": 50, + "end": 51, + "start": 48, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1beta_generated_document_service_create_document_async.py" + "title": "discoveryengine_v1beta_generated_conversational_search_service_update_session_async.py" }, { "canonical": true, "clientMethod": { "client": { - "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceClient", - "shortName": "DocumentServiceClient" + "fullName": "google.cloud.discoveryengine_v1beta.ConversationalSearchServiceClient", + "shortName": "ConversationalSearchServiceClient" }, - "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceClient.create_document", + "fullName": "google.cloud.discoveryengine_v1beta.ConversationalSearchServiceClient.update_session", "method": { - "fullName": "google.cloud.discoveryengine.v1beta.DocumentService.CreateDocument", + "fullName": "google.cloud.discoveryengine.v1beta.ConversationalSearchService.UpdateSession", "service": { - "fullName": "google.cloud.discoveryengine.v1beta.DocumentService", - "shortName": "DocumentService" + "fullName": "google.cloud.discoveryengine.v1beta.ConversationalSearchService", + "shortName": "ConversationalSearchService" }, - "shortName": "CreateDocument" + "shortName": "UpdateSession" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1beta.types.CreateDocumentRequest" - }, - { - "name": "parent", - "type": "str" + "type": "google.cloud.discoveryengine_v1beta.types.UpdateSessionRequest" }, { - "name": "document", - "type": "google.cloud.discoveryengine_v1beta.types.Document" + "name": "session", + "type": "google.cloud.discoveryengine_v1beta.types.Session" }, { - "name": "document_id", - "type": "str" + "name": "update_mask", + "type": "google.protobuf.field_mask_pb2.FieldMask" }, { "name": "retry", @@ -2418,22 +2541,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1beta.types.Document", - "shortName": "create_document" + "resultType": "google.cloud.discoveryengine_v1beta.types.Session", + "shortName": "update_session" }, - "description": "Sample for CreateDocument", - "file": "discoveryengine_v1beta_generated_document_service_create_document_sync.py", + "description": "Sample for UpdateSession", + "file": "discoveryengine_v1beta_generated_conversational_search_service_update_session_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1beta_generated_DocumentService_CreateDocument_sync", + "regionTag": "discoveryengine_v1beta_generated_ConversationalSearchService_UpdateSession_sync", "segments": [ { - "end": 52, + "end": 50, "start": 27, "type": "FULL" }, { - "end": 52, + "end": 50, "start": 27, "type": "SHORT" }, @@ -2443,22 +2566,1811 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 46, + "end": 44, "start": 41, "type": "REQUEST_INITIALIZATION" }, + { + "end": 47, + "start": 45, + "type": "REQUEST_EXECUTION" + }, + { + "end": 51, + "start": 48, + "type": "RESPONSE_HANDLING" + } + ], + "title": "discoveryengine_v1beta_generated_conversational_search_service_update_session_sync.py" + }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.discoveryengine_v1beta.DataStoreServiceAsyncClient", + "shortName": "DataStoreServiceAsyncClient" + }, + "fullName": "google.cloud.discoveryengine_v1beta.DataStoreServiceAsyncClient.create_data_store", + "method": { + "fullName": "google.cloud.discoveryengine.v1beta.DataStoreService.CreateDataStore", + "service": { + "fullName": "google.cloud.discoveryengine.v1beta.DataStoreService", + "shortName": "DataStoreService" + }, + "shortName": "CreateDataStore" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.discoveryengine_v1beta.types.CreateDataStoreRequest" + }, + { + "name": "parent", + "type": "str" + }, + { + "name": "data_store", + "type": "google.cloud.discoveryengine_v1beta.types.DataStore" + }, + { + "name": "data_store_id", + "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": "create_data_store" + }, + "description": "Sample for CreateDataStore", + "file": "discoveryengine_v1beta_generated_data_store_service_create_data_store_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "discoveryengine_v1beta_generated_DataStoreService_CreateDataStore_async", + "segments": [ + { + "end": 60, + "start": 27, + "type": "FULL" + }, + { + "end": 60, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 50, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 57, + "start": 51, + "type": "REQUEST_EXECUTION" + }, + { + "end": 61, + "start": 58, + "type": "RESPONSE_HANDLING" + } + ], + "title": "discoveryengine_v1beta_generated_data_store_service_create_data_store_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.discoveryengine_v1beta.DataStoreServiceClient", + "shortName": "DataStoreServiceClient" + }, + "fullName": "google.cloud.discoveryengine_v1beta.DataStoreServiceClient.create_data_store", + "method": { + "fullName": "google.cloud.discoveryengine.v1beta.DataStoreService.CreateDataStore", + "service": { + "fullName": "google.cloud.discoveryengine.v1beta.DataStoreService", + "shortName": "DataStoreService" + }, + "shortName": "CreateDataStore" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.discoveryengine_v1beta.types.CreateDataStoreRequest" + }, + { + "name": "parent", + "type": "str" + }, + { + "name": "data_store", + "type": "google.cloud.discoveryengine_v1beta.types.DataStore" + }, + { + "name": "data_store_id", + "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": "create_data_store" + }, + "description": "Sample for CreateDataStore", + "file": "discoveryengine_v1beta_generated_data_store_service_create_data_store_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "discoveryengine_v1beta_generated_DataStoreService_CreateDataStore_sync", + "segments": [ + { + "end": 60, + "start": 27, + "type": "FULL" + }, + { + "end": 60, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 50, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 57, + "start": 51, + "type": "REQUEST_EXECUTION" + }, + { + "end": 61, + "start": 58, + "type": "RESPONSE_HANDLING" + } + ], + "title": "discoveryengine_v1beta_generated_data_store_service_create_data_store_sync.py" + }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.discoveryengine_v1beta.DataStoreServiceAsyncClient", + "shortName": "DataStoreServiceAsyncClient" + }, + "fullName": "google.cloud.discoveryengine_v1beta.DataStoreServiceAsyncClient.delete_data_store", + "method": { + "fullName": "google.cloud.discoveryengine.v1beta.DataStoreService.DeleteDataStore", + "service": { + "fullName": "google.cloud.discoveryengine.v1beta.DataStoreService", + "shortName": "DataStoreService" + }, + "shortName": "DeleteDataStore" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.discoveryengine_v1beta.types.DeleteDataStoreRequest" + }, + { + "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": "delete_data_store" + }, + "description": "Sample for DeleteDataStore", + "file": "discoveryengine_v1beta_generated_data_store_service_delete_data_store_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "discoveryengine_v1beta_generated_DataStoreService_DeleteDataStore_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": "discoveryengine_v1beta_generated_data_store_service_delete_data_store_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.discoveryengine_v1beta.DataStoreServiceClient", + "shortName": "DataStoreServiceClient" + }, + "fullName": "google.cloud.discoveryengine_v1beta.DataStoreServiceClient.delete_data_store", + "method": { + "fullName": "google.cloud.discoveryengine.v1beta.DataStoreService.DeleteDataStore", + "service": { + "fullName": "google.cloud.discoveryengine.v1beta.DataStoreService", + "shortName": "DataStoreService" + }, + "shortName": "DeleteDataStore" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.discoveryengine_v1beta.types.DeleteDataStoreRequest" + }, + { + "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": "delete_data_store" + }, + "description": "Sample for DeleteDataStore", + "file": "discoveryengine_v1beta_generated_data_store_service_delete_data_store_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "discoveryengine_v1beta_generated_DataStoreService_DeleteDataStore_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": "discoveryengine_v1beta_generated_data_store_service_delete_data_store_sync.py" + }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.discoveryengine_v1beta.DataStoreServiceAsyncClient", + "shortName": "DataStoreServiceAsyncClient" + }, + "fullName": "google.cloud.discoveryengine_v1beta.DataStoreServiceAsyncClient.get_data_store", + "method": { + "fullName": "google.cloud.discoveryengine.v1beta.DataStoreService.GetDataStore", + "service": { + "fullName": "google.cloud.discoveryengine.v1beta.DataStoreService", + "shortName": "DataStoreService" + }, + "shortName": "GetDataStore" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.discoveryengine_v1beta.types.GetDataStoreRequest" + }, + { + "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.discoveryengine_v1beta.types.DataStore", + "shortName": "get_data_store" + }, + "description": "Sample for GetDataStore", + "file": "discoveryengine_v1beta_generated_data_store_service_get_data_store_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "discoveryengine_v1beta_generated_DataStoreService_GetDataStore_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": "discoveryengine_v1beta_generated_data_store_service_get_data_store_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.discoveryengine_v1beta.DataStoreServiceClient", + "shortName": "DataStoreServiceClient" + }, + "fullName": "google.cloud.discoveryengine_v1beta.DataStoreServiceClient.get_data_store", + "method": { + "fullName": "google.cloud.discoveryengine.v1beta.DataStoreService.GetDataStore", + "service": { + "fullName": "google.cloud.discoveryengine.v1beta.DataStoreService", + "shortName": "DataStoreService" + }, + "shortName": "GetDataStore" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.discoveryengine_v1beta.types.GetDataStoreRequest" + }, + { + "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.discoveryengine_v1beta.types.DataStore", + "shortName": "get_data_store" + }, + "description": "Sample for GetDataStore", + "file": "discoveryengine_v1beta_generated_data_store_service_get_data_store_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "discoveryengine_v1beta_generated_DataStoreService_GetDataStore_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": "discoveryengine_v1beta_generated_data_store_service_get_data_store_sync.py" + }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.discoveryengine_v1beta.DataStoreServiceAsyncClient", + "shortName": "DataStoreServiceAsyncClient" + }, + "fullName": "google.cloud.discoveryengine_v1beta.DataStoreServiceAsyncClient.list_data_stores", + "method": { + "fullName": "google.cloud.discoveryengine.v1beta.DataStoreService.ListDataStores", + "service": { + "fullName": "google.cloud.discoveryengine.v1beta.DataStoreService", + "shortName": "DataStoreService" + }, + "shortName": "ListDataStores" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.discoveryengine_v1beta.types.ListDataStoresRequest" + }, + { + "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.discoveryengine_v1beta.services.data_store_service.pagers.ListDataStoresAsyncPager", + "shortName": "list_data_stores" + }, + "description": "Sample for ListDataStores", + "file": "discoveryengine_v1beta_generated_data_store_service_list_data_stores_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "discoveryengine_v1beta_generated_DataStoreService_ListDataStores_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": "discoveryengine_v1beta_generated_data_store_service_list_data_stores_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.discoveryengine_v1beta.DataStoreServiceClient", + "shortName": "DataStoreServiceClient" + }, + "fullName": "google.cloud.discoveryengine_v1beta.DataStoreServiceClient.list_data_stores", + "method": { + "fullName": "google.cloud.discoveryengine.v1beta.DataStoreService.ListDataStores", + "service": { + "fullName": "google.cloud.discoveryengine.v1beta.DataStoreService", + "shortName": "DataStoreService" + }, + "shortName": "ListDataStores" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.discoveryengine_v1beta.types.ListDataStoresRequest" + }, + { + "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.discoveryengine_v1beta.services.data_store_service.pagers.ListDataStoresPager", + "shortName": "list_data_stores" + }, + "description": "Sample for ListDataStores", + "file": "discoveryengine_v1beta_generated_data_store_service_list_data_stores_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "discoveryengine_v1beta_generated_DataStoreService_ListDataStores_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": "discoveryengine_v1beta_generated_data_store_service_list_data_stores_sync.py" + }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.discoveryengine_v1beta.DataStoreServiceAsyncClient", + "shortName": "DataStoreServiceAsyncClient" + }, + "fullName": "google.cloud.discoveryengine_v1beta.DataStoreServiceAsyncClient.update_data_store", + "method": { + "fullName": "google.cloud.discoveryengine.v1beta.DataStoreService.UpdateDataStore", + "service": { + "fullName": "google.cloud.discoveryengine.v1beta.DataStoreService", + "shortName": "DataStoreService" + }, + "shortName": "UpdateDataStore" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.discoveryengine_v1beta.types.UpdateDataStoreRequest" + }, + { + "name": "data_store", + "type": "google.cloud.discoveryengine_v1beta.types.DataStore" + }, + { + "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.discoveryengine_v1beta.types.DataStore", + "shortName": "update_data_store" + }, + "description": "Sample for UpdateDataStore", + "file": "discoveryengine_v1beta_generated_data_store_service_update_data_store_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "discoveryengine_v1beta_generated_DataStoreService_UpdateDataStore_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": "discoveryengine_v1beta_generated_data_store_service_update_data_store_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.discoveryengine_v1beta.DataStoreServiceClient", + "shortName": "DataStoreServiceClient" + }, + "fullName": "google.cloud.discoveryengine_v1beta.DataStoreServiceClient.update_data_store", + "method": { + "fullName": "google.cloud.discoveryengine.v1beta.DataStoreService.UpdateDataStore", + "service": { + "fullName": "google.cloud.discoveryengine.v1beta.DataStoreService", + "shortName": "DataStoreService" + }, + "shortName": "UpdateDataStore" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.discoveryengine_v1beta.types.UpdateDataStoreRequest" + }, + { + "name": "data_store", + "type": "google.cloud.discoveryengine_v1beta.types.DataStore" + }, + { + "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.discoveryengine_v1beta.types.DataStore", + "shortName": "update_data_store" + }, + "description": "Sample for UpdateDataStore", + "file": "discoveryengine_v1beta_generated_data_store_service_update_data_store_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "discoveryengine_v1beta_generated_DataStoreService_UpdateDataStore_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": "discoveryengine_v1beta_generated_data_store_service_update_data_store_sync.py" + }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceAsyncClient", + "shortName": "DocumentServiceAsyncClient" + }, + "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceAsyncClient.create_document", + "method": { + "fullName": "google.cloud.discoveryengine.v1beta.DocumentService.CreateDocument", + "service": { + "fullName": "google.cloud.discoveryengine.v1beta.DocumentService", + "shortName": "DocumentService" + }, + "shortName": "CreateDocument" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.discoveryengine_v1beta.types.CreateDocumentRequest" + }, + { + "name": "parent", + "type": "str" + }, + { + "name": "document", + "type": "google.cloud.discoveryengine_v1beta.types.Document" + }, + { + "name": "document_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.discoveryengine_v1beta.types.Document", + "shortName": "create_document" + }, + "description": "Sample for CreateDocument", + "file": "discoveryengine_v1beta_generated_document_service_create_document_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "discoveryengine_v1beta_generated_DocumentService_CreateDocument_async", + "segments": [ + { + "end": 52, + "start": 27, + "type": "FULL" + }, + { + "end": 52, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 46, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 49, + "start": 47, + "type": "REQUEST_EXECUTION" + }, + { + "end": 53, + "start": 50, + "type": "RESPONSE_HANDLING" + } + ], + "title": "discoveryengine_v1beta_generated_document_service_create_document_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceClient", + "shortName": "DocumentServiceClient" + }, + "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceClient.create_document", + "method": { + "fullName": "google.cloud.discoveryengine.v1beta.DocumentService.CreateDocument", + "service": { + "fullName": "google.cloud.discoveryengine.v1beta.DocumentService", + "shortName": "DocumentService" + }, + "shortName": "CreateDocument" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.discoveryengine_v1beta.types.CreateDocumentRequest" + }, + { + "name": "parent", + "type": "str" + }, + { + "name": "document", + "type": "google.cloud.discoveryengine_v1beta.types.Document" + }, + { + "name": "document_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.discoveryengine_v1beta.types.Document", + "shortName": "create_document" + }, + "description": "Sample for CreateDocument", + "file": "discoveryengine_v1beta_generated_document_service_create_document_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "discoveryengine_v1beta_generated_DocumentService_CreateDocument_sync", + "segments": [ + { + "end": 52, + "start": 27, + "type": "FULL" + }, + { + "end": 52, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 46, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 49, + "start": 47, + "type": "REQUEST_EXECUTION" + }, + { + "end": 53, + "start": 50, + "type": "RESPONSE_HANDLING" + } + ], + "title": "discoveryengine_v1beta_generated_document_service_create_document_sync.py" + }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceAsyncClient", + "shortName": "DocumentServiceAsyncClient" + }, + "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceAsyncClient.delete_document", + "method": { + "fullName": "google.cloud.discoveryengine.v1beta.DocumentService.DeleteDocument", + "service": { + "fullName": "google.cloud.discoveryengine.v1beta.DocumentService", + "shortName": "DocumentService" + }, + "shortName": "DeleteDocument" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.discoveryengine_v1beta.types.DeleteDocumentRequest" + }, + { + "name": "name", + "type": "str" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "shortName": "delete_document" + }, + "description": "Sample for DeleteDocument", + "file": "discoveryengine_v1beta_generated_document_service_delete_document_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "discoveryengine_v1beta_generated_DocumentService_DeleteDocument_async", + "segments": [ + { + "end": 49, + "start": 27, + "type": "FULL" + }, + { + "end": 49, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 45, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "start": 46, + "type": "REQUEST_EXECUTION" + }, + { + "end": 50, + "type": "RESPONSE_HANDLING" + } + ], + "title": "discoveryengine_v1beta_generated_document_service_delete_document_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceClient", + "shortName": "DocumentServiceClient" + }, + "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceClient.delete_document", + "method": { + "fullName": "google.cloud.discoveryengine.v1beta.DocumentService.DeleteDocument", + "service": { + "fullName": "google.cloud.discoveryengine.v1beta.DocumentService", + "shortName": "DocumentService" + }, + "shortName": "DeleteDocument" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.discoveryengine_v1beta.types.DeleteDocumentRequest" + }, + { + "name": "name", + "type": "str" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, str]" + } + ], + "shortName": "delete_document" + }, + "description": "Sample for DeleteDocument", + "file": "discoveryengine_v1beta_generated_document_service_delete_document_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "discoveryengine_v1beta_generated_DocumentService_DeleteDocument_sync", + "segments": [ + { + "end": 49, + "start": 27, + "type": "FULL" + }, { "end": 49, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 45, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "start": 46, + "type": "REQUEST_EXECUTION" + }, + { + "end": 50, + "type": "RESPONSE_HANDLING" + } + ], + "title": "discoveryengine_v1beta_generated_document_service_delete_document_sync.py" + }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceAsyncClient", + "shortName": "DocumentServiceAsyncClient" + }, + "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceAsyncClient.get_document", + "method": { + "fullName": "google.cloud.discoveryengine.v1beta.DocumentService.GetDocument", + "service": { + "fullName": "google.cloud.discoveryengine.v1beta.DocumentService", + "shortName": "DocumentService" + }, + "shortName": "GetDocument" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.discoveryengine_v1beta.types.GetDocumentRequest" + }, + { + "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.discoveryengine_v1beta.types.Document", + "shortName": "get_document" + }, + "description": "Sample for GetDocument", + "file": "discoveryengine_v1beta_generated_document_service_get_document_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "discoveryengine_v1beta_generated_DocumentService_GetDocument_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": "discoveryengine_v1beta_generated_document_service_get_document_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceClient", + "shortName": "DocumentServiceClient" + }, + "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceClient.get_document", + "method": { + "fullName": "google.cloud.discoveryengine.v1beta.DocumentService.GetDocument", + "service": { + "fullName": "google.cloud.discoveryengine.v1beta.DocumentService", + "shortName": "DocumentService" + }, + "shortName": "GetDocument" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.discoveryengine_v1beta.types.GetDocumentRequest" + }, + { + "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.discoveryengine_v1beta.types.Document", + "shortName": "get_document" + }, + "description": "Sample for GetDocument", + "file": "discoveryengine_v1beta_generated_document_service_get_document_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "discoveryengine_v1beta_generated_DocumentService_GetDocument_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": "discoveryengine_v1beta_generated_document_service_get_document_sync.py" + }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceAsyncClient", + "shortName": "DocumentServiceAsyncClient" + }, + "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceAsyncClient.import_documents", + "method": { + "fullName": "google.cloud.discoveryengine.v1beta.DocumentService.ImportDocuments", + "service": { + "fullName": "google.cloud.discoveryengine.v1beta.DocumentService", + "shortName": "DocumentService" + }, + "shortName": "ImportDocuments" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.discoveryengine_v1beta.types.ImportDocumentsRequest" + }, + { + "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": "import_documents" + }, + "description": "Sample for ImportDocuments", + "file": "discoveryengine_v1beta_generated_document_service_import_documents_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "discoveryengine_v1beta_generated_DocumentService_ImportDocuments_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": "discoveryengine_v1beta_generated_document_service_import_documents_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceClient", + "shortName": "DocumentServiceClient" + }, + "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceClient.import_documents", + "method": { + "fullName": "google.cloud.discoveryengine.v1beta.DocumentService.ImportDocuments", + "service": { + "fullName": "google.cloud.discoveryengine.v1beta.DocumentService", + "shortName": "DocumentService" + }, + "shortName": "ImportDocuments" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.discoveryengine_v1beta.types.ImportDocumentsRequest" + }, + { + "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": "import_documents" + }, + "description": "Sample for ImportDocuments", + "file": "discoveryengine_v1beta_generated_document_service_import_documents_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "discoveryengine_v1beta_generated_DocumentService_ImportDocuments_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": "discoveryengine_v1beta_generated_document_service_import_documents_sync.py" + }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceAsyncClient", + "shortName": "DocumentServiceAsyncClient" + }, + "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceAsyncClient.list_documents", + "method": { + "fullName": "google.cloud.discoveryengine.v1beta.DocumentService.ListDocuments", + "service": { + "fullName": "google.cloud.discoveryengine.v1beta.DocumentService", + "shortName": "DocumentService" + }, + "shortName": "ListDocuments" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.discoveryengine_v1beta.types.ListDocumentsRequest" + }, + { + "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.discoveryengine_v1beta.services.document_service.pagers.ListDocumentsAsyncPager", + "shortName": "list_documents" + }, + "description": "Sample for ListDocuments", + "file": "discoveryengine_v1beta_generated_document_service_list_documents_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "discoveryengine_v1beta_generated_DocumentService_ListDocuments_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": "discoveryengine_v1beta_generated_document_service_list_documents_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceClient", + "shortName": "DocumentServiceClient" + }, + "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceClient.list_documents", + "method": { + "fullName": "google.cloud.discoveryengine.v1beta.DocumentService.ListDocuments", + "service": { + "fullName": "google.cloud.discoveryengine.v1beta.DocumentService", + "shortName": "DocumentService" + }, + "shortName": "ListDocuments" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.discoveryengine_v1beta.types.ListDocumentsRequest" + }, + { + "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.discoveryengine_v1beta.services.document_service.pagers.ListDocumentsPager", + "shortName": "list_documents" + }, + "description": "Sample for ListDocuments", + "file": "discoveryengine_v1beta_generated_document_service_list_documents_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "discoveryengine_v1beta_generated_DocumentService_ListDocuments_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": "discoveryengine_v1beta_generated_document_service_list_documents_sync.py" + }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceAsyncClient", + "shortName": "DocumentServiceAsyncClient" + }, + "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceAsyncClient.purge_documents", + "method": { + "fullName": "google.cloud.discoveryengine.v1beta.DocumentService.PurgeDocuments", + "service": { + "fullName": "google.cloud.discoveryengine.v1beta.DocumentService", + "shortName": "DocumentService" + }, + "shortName": "PurgeDocuments" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.discoveryengine_v1beta.types.PurgeDocumentsRequest" + }, + { + "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": "purge_documents" + }, + "description": "Sample for PurgeDocuments", + "file": "discoveryengine_v1beta_generated_document_service_purge_documents_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "discoveryengine_v1beta_generated_DocumentService_PurgeDocuments_async", + "segments": [ + { + "end": 56, + "start": 27, + "type": "FULL" + }, + { + "end": 56, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 46, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 53, "start": 47, "type": "REQUEST_EXECUTION" }, + { + "end": 57, + "start": 54, + "type": "RESPONSE_HANDLING" + } + ], + "title": "discoveryengine_v1beta_generated_document_service_purge_documents_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceClient", + "shortName": "DocumentServiceClient" + }, + "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceClient.purge_documents", + "method": { + "fullName": "google.cloud.discoveryengine.v1beta.DocumentService.PurgeDocuments", + "service": { + "fullName": "google.cloud.discoveryengine.v1beta.DocumentService", + "shortName": "DocumentService" + }, + "shortName": "PurgeDocuments" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.discoveryengine_v1beta.types.PurgeDocumentsRequest" + }, + { + "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": "purge_documents" + }, + "description": "Sample for PurgeDocuments", + "file": "discoveryengine_v1beta_generated_document_service_purge_documents_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "discoveryengine_v1beta_generated_DocumentService_PurgeDocuments_sync", + "segments": [ + { + "end": 56, + "start": 27, + "type": "FULL" + }, + { + "end": 56, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 46, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, { "end": 53, - "start": 50, + "start": 47, + "type": "REQUEST_EXECUTION" + }, + { + "end": 57, + "start": 54, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1beta_generated_document_service_create_document_sync.py" + "title": "discoveryengine_v1beta_generated_document_service_purge_documents_sync.py" }, { "canonical": true, @@ -2468,23 +4380,27 @@ "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceAsyncClient", "shortName": "DocumentServiceAsyncClient" }, - "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceAsyncClient.delete_document", + "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceAsyncClient.update_document", "method": { - "fullName": "google.cloud.discoveryengine.v1beta.DocumentService.DeleteDocument", + "fullName": "google.cloud.discoveryengine.v1beta.DocumentService.UpdateDocument", "service": { "fullName": "google.cloud.discoveryengine.v1beta.DocumentService", "shortName": "DocumentService" }, - "shortName": "DeleteDocument" + "shortName": "UpdateDocument" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1beta.types.DeleteDocumentRequest" + "type": "google.cloud.discoveryengine_v1beta.types.UpdateDocumentRequest" }, { - "name": "name", - "type": "str" + "name": "document", + "type": "google.cloud.discoveryengine_v1beta.types.Document" + }, + { + "name": "update_mask", + "type": "google.protobuf.field_mask_pb2.FieldMask" }, { "name": "retry", @@ -2499,21 +4415,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "shortName": "delete_document" + "resultType": "google.cloud.discoveryengine_v1beta.types.Document", + "shortName": "update_document" }, - "description": "Sample for DeleteDocument", - "file": "discoveryengine_v1beta_generated_document_service_delete_document_async.py", + "description": "Sample for UpdateDocument", + "file": "discoveryengine_v1beta_generated_document_service_update_document_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1beta_generated_DocumentService_DeleteDocument_async", + "regionTag": "discoveryengine_v1beta_generated_DocumentService_UpdateDocument_async", "segments": [ { - "end": 49, + "end": 50, "start": 27, "type": "FULL" }, { - "end": 49, + "end": 50, "start": 27, "type": "SHORT" }, @@ -2523,20 +4440,22 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 45, + "end": 44, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "start": 46, + "end": 47, + "start": 45, "type": "REQUEST_EXECUTION" }, { - "end": 50, + "end": 51, + "start": 48, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1beta_generated_document_service_delete_document_async.py" + "title": "discoveryengine_v1beta_generated_document_service_update_document_async.py" }, { "canonical": true, @@ -2545,23 +4464,27 @@ "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceClient", "shortName": "DocumentServiceClient" }, - "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceClient.delete_document", + "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceClient.update_document", "method": { - "fullName": "google.cloud.discoveryengine.v1beta.DocumentService.DeleteDocument", + "fullName": "google.cloud.discoveryengine.v1beta.DocumentService.UpdateDocument", "service": { "fullName": "google.cloud.discoveryengine.v1beta.DocumentService", "shortName": "DocumentService" }, - "shortName": "DeleteDocument" + "shortName": "UpdateDocument" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1beta.types.DeleteDocumentRequest" + "type": "google.cloud.discoveryengine_v1beta.types.UpdateDocumentRequest" }, { - "name": "name", - "type": "str" + "name": "document", + "type": "google.cloud.discoveryengine_v1beta.types.Document" + }, + { + "name": "update_mask", + "type": "google.protobuf.field_mask_pb2.FieldMask" }, { "name": "retry", @@ -2576,21 +4499,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "shortName": "delete_document" + "resultType": "google.cloud.discoveryengine_v1beta.types.Document", + "shortName": "update_document" }, - "description": "Sample for DeleteDocument", - "file": "discoveryengine_v1beta_generated_document_service_delete_document_sync.py", + "description": "Sample for UpdateDocument", + "file": "discoveryengine_v1beta_generated_document_service_update_document_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1beta_generated_DocumentService_DeleteDocument_sync", + "regionTag": "discoveryengine_v1beta_generated_DocumentService_UpdateDocument_sync", "segments": [ { - "end": 49, + "end": 50, "start": 27, "type": "FULL" }, { - "end": 49, + "end": 50, "start": 27, "type": "SHORT" }, @@ -2600,45 +4524,55 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 45, + "end": 44, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "start": 46, + "end": 47, + "start": 45, "type": "REQUEST_EXECUTION" }, { - "end": 50, + "end": 51, + "start": 48, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1beta_generated_document_service_delete_document_sync.py" + "title": "discoveryengine_v1beta_generated_document_service_update_document_sync.py" }, { "canonical": true, "clientMethod": { "async": true, "client": { - "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceAsyncClient", - "shortName": "DocumentServiceAsyncClient" + "fullName": "google.cloud.discoveryengine_v1beta.EngineServiceAsyncClient", + "shortName": "EngineServiceAsyncClient" }, - "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceAsyncClient.get_document", + "fullName": "google.cloud.discoveryengine_v1beta.EngineServiceAsyncClient.create_engine", "method": { - "fullName": "google.cloud.discoveryengine.v1beta.DocumentService.GetDocument", + "fullName": "google.cloud.discoveryengine.v1beta.EngineService.CreateEngine", "service": { - "fullName": "google.cloud.discoveryengine.v1beta.DocumentService", - "shortName": "DocumentService" + "fullName": "google.cloud.discoveryengine.v1beta.EngineService", + "shortName": "EngineService" }, - "shortName": "GetDocument" + "shortName": "CreateEngine" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1beta.types.GetDocumentRequest" + "type": "google.cloud.discoveryengine_v1beta.types.CreateEngineRequest" }, { - "name": "name", + "name": "parent", + "type": "str" + }, + { + "name": "engine", + "type": "google.cloud.discoveryengine_v1beta.types.Engine" + }, + { + "name": "engine_id", "type": "str" }, { @@ -2654,22 +4588,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1beta.types.Document", - "shortName": "get_document" + "resultType": "google.api_core.operation_async.AsyncOperation", + "shortName": "create_engine" }, - "description": "Sample for GetDocument", - "file": "discoveryengine_v1beta_generated_document_service_get_document_async.py", + "description": "Sample for CreateEngine", + "file": "discoveryengine_v1beta_generated_engine_service_create_engine_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1beta_generated_DocumentService_GetDocument_async", + "regionTag": "discoveryengine_v1beta_generated_EngineService_CreateEngine_async", "segments": [ { - "end": 51, + "end": 61, "start": 27, "type": "FULL" }, { - "end": 51, + "end": 61, "start": 27, "type": "SHORT" }, @@ -2679,46 +4613,54 @@ "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": "discoveryengine_v1beta_generated_document_service_get_document_async.py" + "title": "discoveryengine_v1beta_generated_engine_service_create_engine_async.py" }, { "canonical": true, "clientMethod": { "client": { - "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceClient", - "shortName": "DocumentServiceClient" + "fullName": "google.cloud.discoveryengine_v1beta.EngineServiceClient", + "shortName": "EngineServiceClient" }, - "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceClient.get_document", + "fullName": "google.cloud.discoveryengine_v1beta.EngineServiceClient.create_engine", "method": { - "fullName": "google.cloud.discoveryengine.v1beta.DocumentService.GetDocument", + "fullName": "google.cloud.discoveryengine.v1beta.EngineService.CreateEngine", "service": { - "fullName": "google.cloud.discoveryengine.v1beta.DocumentService", - "shortName": "DocumentService" + "fullName": "google.cloud.discoveryengine.v1beta.EngineService", + "shortName": "EngineService" }, - "shortName": "GetDocument" + "shortName": "CreateEngine" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1beta.types.GetDocumentRequest" + "type": "google.cloud.discoveryengine_v1beta.types.CreateEngineRequest" }, { - "name": "name", + "name": "parent", + "type": "str" + }, + { + "name": "engine", + "type": "google.cloud.discoveryengine_v1beta.types.Engine" + }, + { + "name": "engine_id", "type": "str" }, { @@ -2734,22 +4676,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1beta.types.Document", - "shortName": "get_document" + "resultType": "google.api_core.operation.Operation", + "shortName": "create_engine" }, - "description": "Sample for GetDocument", - "file": "discoveryengine_v1beta_generated_document_service_get_document_sync.py", + "description": "Sample for CreateEngine", + "file": "discoveryengine_v1beta_generated_engine_service_create_engine_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1beta_generated_DocumentService_GetDocument_sync", + "regionTag": "discoveryengine_v1beta_generated_EngineService_CreateEngine_sync", "segments": [ { - "end": 51, + "end": 61, "start": 27, "type": "FULL" }, { - "end": 51, + "end": 61, "start": 27, "type": "SHORT" }, @@ -2759,44 +4701,48 @@ "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": "discoveryengine_v1beta_generated_document_service_get_document_sync.py" + "title": "discoveryengine_v1beta_generated_engine_service_create_engine_sync.py" }, { "canonical": true, "clientMethod": { "async": true, "client": { - "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceAsyncClient", - "shortName": "DocumentServiceAsyncClient" + "fullName": "google.cloud.discoveryengine_v1beta.EngineServiceAsyncClient", + "shortName": "EngineServiceAsyncClient" }, - "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceAsyncClient.import_documents", + "fullName": "google.cloud.discoveryengine_v1beta.EngineServiceAsyncClient.delete_engine", "method": { - "fullName": "google.cloud.discoveryengine.v1beta.DocumentService.ImportDocuments", + "fullName": "google.cloud.discoveryengine.v1beta.EngineService.DeleteEngine", "service": { - "fullName": "google.cloud.discoveryengine.v1beta.DocumentService", - "shortName": "DocumentService" + "fullName": "google.cloud.discoveryengine.v1beta.EngineService", + "shortName": "EngineService" }, - "shortName": "ImportDocuments" + "shortName": "DeleteEngine" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1beta.types.ImportDocumentsRequest" + "type": "google.cloud.discoveryengine_v1beta.types.DeleteEngineRequest" + }, + { + "name": "name", + "type": "str" }, { "name": "retry", @@ -2812,13 +4758,13 @@ } ], "resultType": "google.api_core.operation_async.AsyncOperation", - "shortName": "import_documents" + "shortName": "delete_engine" }, - "description": "Sample for ImportDocuments", - "file": "discoveryengine_v1beta_generated_document_service_import_documents_async.py", + "description": "Sample for DeleteEngine", + "file": "discoveryengine_v1beta_generated_engine_service_delete_engine_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1beta_generated_DocumentService_ImportDocuments_async", + "regionTag": "discoveryengine_v1beta_generated_EngineService_DeleteEngine_async", "segments": [ { "end": 55, @@ -2851,28 +4797,32 @@ "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1beta_generated_document_service_import_documents_async.py" + "title": "discoveryengine_v1beta_generated_engine_service_delete_engine_async.py" }, { "canonical": true, "clientMethod": { "client": { - "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceClient", - "shortName": "DocumentServiceClient" + "fullName": "google.cloud.discoveryengine_v1beta.EngineServiceClient", + "shortName": "EngineServiceClient" }, - "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceClient.import_documents", + "fullName": "google.cloud.discoveryengine_v1beta.EngineServiceClient.delete_engine", "method": { - "fullName": "google.cloud.discoveryengine.v1beta.DocumentService.ImportDocuments", + "fullName": "google.cloud.discoveryengine.v1beta.EngineService.DeleteEngine", "service": { - "fullName": "google.cloud.discoveryengine.v1beta.DocumentService", - "shortName": "DocumentService" + "fullName": "google.cloud.discoveryengine.v1beta.EngineService", + "shortName": "EngineService" }, - "shortName": "ImportDocuments" + "shortName": "DeleteEngine" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1beta.types.ImportDocumentsRequest" + "type": "google.cloud.discoveryengine_v1beta.types.DeleteEngineRequest" + }, + { + "name": "name", + "type": "str" }, { "name": "retry", @@ -2888,13 +4838,13 @@ } ], "resultType": "google.api_core.operation.Operation", - "shortName": "import_documents" + "shortName": "delete_engine" }, - "description": "Sample for ImportDocuments", - "file": "discoveryengine_v1beta_generated_document_service_import_documents_sync.py", + "description": "Sample for DeleteEngine", + "file": "discoveryengine_v1beta_generated_engine_service_delete_engine_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1beta_generated_DocumentService_ImportDocuments_sync", + "regionTag": "discoveryengine_v1beta_generated_EngineService_DeleteEngine_sync", "segments": [ { "end": 55, @@ -2927,32 +4877,32 @@ "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1beta_generated_document_service_import_documents_sync.py" + "title": "discoveryengine_v1beta_generated_engine_service_delete_engine_sync.py" }, { "canonical": true, "clientMethod": { "async": true, "client": { - "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceAsyncClient", - "shortName": "DocumentServiceAsyncClient" + "fullName": "google.cloud.discoveryengine_v1beta.EngineServiceAsyncClient", + "shortName": "EngineServiceAsyncClient" }, - "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceAsyncClient.list_documents", + "fullName": "google.cloud.discoveryengine_v1beta.EngineServiceAsyncClient.get_engine", "method": { - "fullName": "google.cloud.discoveryengine.v1beta.DocumentService.ListDocuments", + "fullName": "google.cloud.discoveryengine.v1beta.EngineService.GetEngine", "service": { - "fullName": "google.cloud.discoveryengine.v1beta.DocumentService", - "shortName": "DocumentService" + "fullName": "google.cloud.discoveryengine.v1beta.EngineService", + "shortName": "EngineService" }, - "shortName": "ListDocuments" + "shortName": "GetEngine" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1beta.types.ListDocumentsRequest" + "type": "google.cloud.discoveryengine_v1beta.types.GetEngineRequest" }, { - "name": "parent", + "name": "name", "type": "str" }, { @@ -2968,22 +4918,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1beta.services.document_service.pagers.ListDocumentsAsyncPager", - "shortName": "list_documents" + "resultType": "google.cloud.discoveryengine_v1beta.types.Engine", + "shortName": "get_engine" }, - "description": "Sample for ListDocuments", - "file": "discoveryengine_v1beta_generated_document_service_list_documents_async.py", + "description": "Sample for GetEngine", + "file": "discoveryengine_v1beta_generated_engine_service_get_engine_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1beta_generated_DocumentService_ListDocuments_async", + "regionTag": "discoveryengine_v1beta_generated_EngineService_GetEngine_async", "segments": [ { - "end": 52, + "end": 51, "start": 27, "type": "FULL" }, { - "end": 52, + "end": 51, "start": 27, "type": "SHORT" }, @@ -3003,36 +4953,36 @@ "type": "REQUEST_EXECUTION" }, { - "end": 53, + "end": 52, "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1beta_generated_document_service_list_documents_async.py" + "title": "discoveryengine_v1beta_generated_engine_service_get_engine_async.py" }, { "canonical": true, "clientMethod": { "client": { - "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceClient", - "shortName": "DocumentServiceClient" + "fullName": "google.cloud.discoveryengine_v1beta.EngineServiceClient", + "shortName": "EngineServiceClient" }, - "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceClient.list_documents", + "fullName": "google.cloud.discoveryengine_v1beta.EngineServiceClient.get_engine", "method": { - "fullName": "google.cloud.discoveryengine.v1beta.DocumentService.ListDocuments", + "fullName": "google.cloud.discoveryengine.v1beta.EngineService.GetEngine", "service": { - "fullName": "google.cloud.discoveryengine.v1beta.DocumentService", - "shortName": "DocumentService" + "fullName": "google.cloud.discoveryengine.v1beta.EngineService", + "shortName": "EngineService" }, - "shortName": "ListDocuments" + "shortName": "GetEngine" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1beta.types.ListDocumentsRequest" + "type": "google.cloud.discoveryengine_v1beta.types.GetEngineRequest" }, { - "name": "parent", + "name": "name", "type": "str" }, { @@ -3048,22 +4998,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1beta.services.document_service.pagers.ListDocumentsPager", - "shortName": "list_documents" + "resultType": "google.cloud.discoveryengine_v1beta.types.Engine", + "shortName": "get_engine" }, - "description": "Sample for ListDocuments", - "file": "discoveryengine_v1beta_generated_document_service_list_documents_sync.py", + "description": "Sample for GetEngine", + "file": "discoveryengine_v1beta_generated_engine_service_get_engine_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1beta_generated_DocumentService_ListDocuments_sync", + "regionTag": "discoveryengine_v1beta_generated_EngineService_GetEngine_sync", "segments": [ { - "end": 52, + "end": 51, "start": 27, "type": "FULL" }, { - "end": 52, + "end": 51, "start": 27, "type": "SHORT" }, @@ -3083,34 +5033,38 @@ "type": "REQUEST_EXECUTION" }, { - "end": 53, + "end": 52, "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1beta_generated_document_service_list_documents_sync.py" + "title": "discoveryengine_v1beta_generated_engine_service_get_engine_sync.py" }, { "canonical": true, "clientMethod": { "async": true, "client": { - "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceAsyncClient", - "shortName": "DocumentServiceAsyncClient" + "fullName": "google.cloud.discoveryengine_v1beta.EngineServiceAsyncClient", + "shortName": "EngineServiceAsyncClient" }, - "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceAsyncClient.purge_documents", + "fullName": "google.cloud.discoveryengine_v1beta.EngineServiceAsyncClient.list_engines", "method": { - "fullName": "google.cloud.discoveryengine.v1beta.DocumentService.PurgeDocuments", + "fullName": "google.cloud.discoveryengine.v1beta.EngineService.ListEngines", "service": { - "fullName": "google.cloud.discoveryengine.v1beta.DocumentService", - "shortName": "DocumentService" + "fullName": "google.cloud.discoveryengine.v1beta.EngineService", + "shortName": "EngineService" }, - "shortName": "PurgeDocuments" + "shortName": "ListEngines" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1beta.types.PurgeDocumentsRequest" + "type": "google.cloud.discoveryengine_v1beta.types.ListEnginesRequest" + }, + { + "name": "parent", + "type": "str" }, { "name": "retry", @@ -3125,22 +5079,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.api_core.operation_async.AsyncOperation", - "shortName": "purge_documents" + "resultType": "google.cloud.discoveryengine_v1beta.services.engine_service.pagers.ListEnginesAsyncPager", + "shortName": "list_engines" }, - "description": "Sample for PurgeDocuments", - "file": "discoveryengine_v1beta_generated_document_service_purge_documents_async.py", + "description": "Sample for ListEngines", + "file": "discoveryengine_v1beta_generated_engine_service_list_engines_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1beta_generated_DocumentService_PurgeDocuments_async", + "regionTag": "discoveryengine_v1beta_generated_EngineService_ListEngines_async", "segments": [ { - "end": 56, + "end": 52, "start": 27, "type": "FULL" }, { - "end": 56, + "end": 52, "start": 27, "type": "SHORT" }, @@ -3150,43 +5104,47 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 46, + "end": 45, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 53, - "start": 47, + "end": 48, + "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 57, - "start": 54, + "end": 53, + "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1beta_generated_document_service_purge_documents_async.py" + "title": "discoveryengine_v1beta_generated_engine_service_list_engines_async.py" }, { "canonical": true, "clientMethod": { "client": { - "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceClient", - "shortName": "DocumentServiceClient" + "fullName": "google.cloud.discoveryengine_v1beta.EngineServiceClient", + "shortName": "EngineServiceClient" }, - "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceClient.purge_documents", + "fullName": "google.cloud.discoveryengine_v1beta.EngineServiceClient.list_engines", "method": { - "fullName": "google.cloud.discoveryengine.v1beta.DocumentService.PurgeDocuments", + "fullName": "google.cloud.discoveryengine.v1beta.EngineService.ListEngines", "service": { - "fullName": "google.cloud.discoveryengine.v1beta.DocumentService", - "shortName": "DocumentService" + "fullName": "google.cloud.discoveryengine.v1beta.EngineService", + "shortName": "EngineService" }, - "shortName": "PurgeDocuments" + "shortName": "ListEngines" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1beta.types.PurgeDocumentsRequest" + "type": "google.cloud.discoveryengine_v1beta.types.ListEnginesRequest" + }, + { + "name": "parent", + "type": "str" }, { "name": "retry", @@ -3201,22 +5159,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.api_core.operation.Operation", - "shortName": "purge_documents" + "resultType": "google.cloud.discoveryengine_v1beta.services.engine_service.pagers.ListEnginesPager", + "shortName": "list_engines" }, - "description": "Sample for PurgeDocuments", - "file": "discoveryengine_v1beta_generated_document_service_purge_documents_sync.py", + "description": "Sample for ListEngines", + "file": "discoveryengine_v1beta_generated_engine_service_list_engines_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1beta_generated_DocumentService_PurgeDocuments_sync", + "regionTag": "discoveryengine_v1beta_generated_EngineService_ListEngines_sync", "segments": [ { - "end": 56, + "end": 52, "start": 27, "type": "FULL" }, { - "end": 56, + "end": 52, "start": 27, "type": "SHORT" }, @@ -3226,44 +5184,48 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 46, + "end": 45, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 53, - "start": 47, + "end": 48, + "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 57, - "start": 54, + "end": 53, + "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1beta_generated_document_service_purge_documents_sync.py" + "title": "discoveryengine_v1beta_generated_engine_service_list_engines_sync.py" }, { "canonical": true, "clientMethod": { "async": true, "client": { - "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceAsyncClient", - "shortName": "DocumentServiceAsyncClient" + "fullName": "google.cloud.discoveryengine_v1beta.EngineServiceAsyncClient", + "shortName": "EngineServiceAsyncClient" }, - "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceAsyncClient.update_document", + "fullName": "google.cloud.discoveryengine_v1beta.EngineServiceAsyncClient.pause_engine", "method": { - "fullName": "google.cloud.discoveryengine.v1beta.DocumentService.UpdateDocument", + "fullName": "google.cloud.discoveryengine.v1beta.EngineService.PauseEngine", "service": { - "fullName": "google.cloud.discoveryengine.v1beta.DocumentService", - "shortName": "DocumentService" + "fullName": "google.cloud.discoveryengine.v1beta.EngineService", + "shortName": "EngineService" }, - "shortName": "UpdateDocument" + "shortName": "PauseEngine" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1beta.types.UpdateDocumentRequest" + "type": "google.cloud.discoveryengine_v1beta.types.PauseEngineRequest" + }, + { + "name": "name", + "type": "str" }, { "name": "retry", @@ -3278,22 +5240,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1beta.types.Document", - "shortName": "update_document" + "resultType": "google.cloud.discoveryengine_v1beta.types.Engine", + "shortName": "pause_engine" }, - "description": "Sample for UpdateDocument", - "file": "discoveryengine_v1beta_generated_document_service_update_document_async.py", + "description": "Sample for PauseEngine", + "file": "discoveryengine_v1beta_generated_engine_service_pause_engine_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1beta_generated_DocumentService_UpdateDocument_async", + "regionTag": "discoveryengine_v1beta_generated_EngineService_PauseEngine_async", "segments": [ { - "end": 50, + "end": 51, "start": 27, "type": "FULL" }, { - "end": 50, + "end": 51, "start": 27, "type": "SHORT" }, @@ -3303,43 +5265,47 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 44, + "end": 45, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 47, - "start": 45, + "end": 48, + "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 51, - "start": 48, + "end": 52, + "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1beta_generated_document_service_update_document_async.py" + "title": "discoveryengine_v1beta_generated_engine_service_pause_engine_async.py" }, { "canonical": true, "clientMethod": { "client": { - "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceClient", - "shortName": "DocumentServiceClient" + "fullName": "google.cloud.discoveryengine_v1beta.EngineServiceClient", + "shortName": "EngineServiceClient" }, - "fullName": "google.cloud.discoveryengine_v1beta.DocumentServiceClient.update_document", + "fullName": "google.cloud.discoveryengine_v1beta.EngineServiceClient.pause_engine", "method": { - "fullName": "google.cloud.discoveryengine.v1beta.DocumentService.UpdateDocument", + "fullName": "google.cloud.discoveryengine.v1beta.EngineService.PauseEngine", "service": { - "fullName": "google.cloud.discoveryengine.v1beta.DocumentService", - "shortName": "DocumentService" + "fullName": "google.cloud.discoveryengine.v1beta.EngineService", + "shortName": "EngineService" }, - "shortName": "UpdateDocument" + "shortName": "PauseEngine" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1beta.types.UpdateDocumentRequest" + "type": "google.cloud.discoveryengine_v1beta.types.PauseEngineRequest" + }, + { + "name": "name", + "type": "str" }, { "name": "retry", @@ -3354,22 +5320,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1beta.types.Document", - "shortName": "update_document" + "resultType": "google.cloud.discoveryengine_v1beta.types.Engine", + "shortName": "pause_engine" }, - "description": "Sample for UpdateDocument", - "file": "discoveryengine_v1beta_generated_document_service_update_document_sync.py", + "description": "Sample for PauseEngine", + "file": "discoveryengine_v1beta_generated_engine_service_pause_engine_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1beta_generated_DocumentService_UpdateDocument_sync", + "regionTag": "discoveryengine_v1beta_generated_EngineService_PauseEngine_sync", "segments": [ { - "end": 50, + "end": 51, "start": 27, "type": "FULL" }, { - "end": 50, + "end": 51, "start": 27, "type": "SHORT" }, @@ -3379,22 +5345,22 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 44, + "end": 45, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 47, - "start": 45, + "end": 48, + "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 51, - "start": 48, + "end": 52, + "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1beta_generated_document_service_update_document_sync.py" + "title": "discoveryengine_v1beta_generated_engine_service_pause_engine_sync.py" }, { "canonical": true, @@ -3404,30 +5370,22 @@ "fullName": "google.cloud.discoveryengine_v1beta.EngineServiceAsyncClient", "shortName": "EngineServiceAsyncClient" }, - "fullName": "google.cloud.discoveryengine_v1beta.EngineServiceAsyncClient.create_engine", + "fullName": "google.cloud.discoveryengine_v1beta.EngineServiceAsyncClient.resume_engine", "method": { - "fullName": "google.cloud.discoveryengine.v1beta.EngineService.CreateEngine", + "fullName": "google.cloud.discoveryengine.v1beta.EngineService.ResumeEngine", "service": { "fullName": "google.cloud.discoveryengine.v1beta.EngineService", "shortName": "EngineService" }, - "shortName": "CreateEngine" + "shortName": "ResumeEngine" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1beta.types.CreateEngineRequest" - }, - { - "name": "parent", - "type": "str" + "type": "google.cloud.discoveryengine_v1beta.types.ResumeEngineRequest" }, { - "name": "engine", - "type": "google.cloud.discoveryengine_v1beta.types.Engine" - }, - { - "name": "engine_id", + "name": "name", "type": "str" }, { @@ -3443,22 +5401,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.api_core.operation_async.AsyncOperation", - "shortName": "create_engine" + "resultType": "google.cloud.discoveryengine_v1beta.types.Engine", + "shortName": "resume_engine" }, - "description": "Sample for CreateEngine", - "file": "discoveryengine_v1beta_generated_engine_service_create_engine_async.py", + "description": "Sample for ResumeEngine", + "file": "discoveryengine_v1beta_generated_engine_service_resume_engine_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1beta_generated_EngineService_CreateEngine_async", + "regionTag": "discoveryengine_v1beta_generated_EngineService_ResumeEngine_async", "segments": [ { - "end": 61, + "end": 51, "start": 27, "type": "FULL" }, { - "end": 61, + "end": 51, "start": 27, "type": "SHORT" }, @@ -3468,22 +5426,22 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 51, + "end": 45, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 58, - "start": 52, + "end": 48, + "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 62, - "start": 59, + "end": 52, + "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1beta_generated_engine_service_create_engine_async.py" + "title": "discoveryengine_v1beta_generated_engine_service_resume_engine_async.py" }, { "canonical": true, @@ -3492,30 +5450,22 @@ "fullName": "google.cloud.discoveryengine_v1beta.EngineServiceClient", "shortName": "EngineServiceClient" }, - "fullName": "google.cloud.discoveryengine_v1beta.EngineServiceClient.create_engine", + "fullName": "google.cloud.discoveryengine_v1beta.EngineServiceClient.resume_engine", "method": { - "fullName": "google.cloud.discoveryengine.v1beta.EngineService.CreateEngine", + "fullName": "google.cloud.discoveryengine.v1beta.EngineService.ResumeEngine", "service": { "fullName": "google.cloud.discoveryengine.v1beta.EngineService", "shortName": "EngineService" }, - "shortName": "CreateEngine" + "shortName": "ResumeEngine" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1beta.types.CreateEngineRequest" - }, - { - "name": "parent", - "type": "str" - }, - { - "name": "engine", - "type": "google.cloud.discoveryengine_v1beta.types.Engine" + "type": "google.cloud.discoveryengine_v1beta.types.ResumeEngineRequest" }, { - "name": "engine_id", + "name": "name", "type": "str" }, { @@ -3531,22 +5481,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.api_core.operation.Operation", - "shortName": "create_engine" + "resultType": "google.cloud.discoveryengine_v1beta.types.Engine", + "shortName": "resume_engine" }, - "description": "Sample for CreateEngine", - "file": "discoveryengine_v1beta_generated_engine_service_create_engine_sync.py", + "description": "Sample for ResumeEngine", + "file": "discoveryengine_v1beta_generated_engine_service_resume_engine_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1beta_generated_EngineService_CreateEngine_sync", + "regionTag": "discoveryengine_v1beta_generated_EngineService_ResumeEngine_sync", "segments": [ { - "end": 61, + "end": 51, "start": 27, "type": "FULL" }, { - "end": 61, + "end": 51, "start": 27, "type": "SHORT" }, @@ -3556,22 +5506,22 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 51, + "end": 45, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 58, - "start": 52, + "end": 48, + "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 62, - "start": 59, + "end": 52, + "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1beta_generated_engine_service_create_engine_sync.py" + "title": "discoveryengine_v1beta_generated_engine_service_resume_engine_sync.py" }, { "canonical": true, @@ -3581,19 +5531,19 @@ "fullName": "google.cloud.discoveryengine_v1beta.EngineServiceAsyncClient", "shortName": "EngineServiceAsyncClient" }, - "fullName": "google.cloud.discoveryengine_v1beta.EngineServiceAsyncClient.delete_engine", + "fullName": "google.cloud.discoveryengine_v1beta.EngineServiceAsyncClient.tune_engine", "method": { - "fullName": "google.cloud.discoveryengine.v1beta.EngineService.DeleteEngine", + "fullName": "google.cloud.discoveryengine.v1beta.EngineService.TuneEngine", "service": { "fullName": "google.cloud.discoveryengine.v1beta.EngineService", "shortName": "EngineService" }, - "shortName": "DeleteEngine" + "shortName": "TuneEngine" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1beta.types.DeleteEngineRequest" + "type": "google.cloud.discoveryengine_v1beta.types.TuneEngineRequest" }, { "name": "name", @@ -3613,13 +5563,13 @@ } ], "resultType": "google.api_core.operation_async.AsyncOperation", - "shortName": "delete_engine" + "shortName": "tune_engine" }, - "description": "Sample for DeleteEngine", - "file": "discoveryengine_v1beta_generated_engine_service_delete_engine_async.py", + "description": "Sample for TuneEngine", + "file": "discoveryengine_v1beta_generated_engine_service_tune_engine_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1beta_generated_EngineService_DeleteEngine_async", + "regionTag": "discoveryengine_v1beta_generated_EngineService_TuneEngine_async", "segments": [ { "end": 55, @@ -3652,7 +5602,7 @@ "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1beta_generated_engine_service_delete_engine_async.py" + "title": "discoveryengine_v1beta_generated_engine_service_tune_engine_async.py" }, { "canonical": true, @@ -3661,19 +5611,19 @@ "fullName": "google.cloud.discoveryengine_v1beta.EngineServiceClient", "shortName": "EngineServiceClient" }, - "fullName": "google.cloud.discoveryengine_v1beta.EngineServiceClient.delete_engine", + "fullName": "google.cloud.discoveryengine_v1beta.EngineServiceClient.tune_engine", "method": { - "fullName": "google.cloud.discoveryengine.v1beta.EngineService.DeleteEngine", + "fullName": "google.cloud.discoveryengine.v1beta.EngineService.TuneEngine", "service": { "fullName": "google.cloud.discoveryengine.v1beta.EngineService", "shortName": "EngineService" }, - "shortName": "DeleteEngine" + "shortName": "TuneEngine" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1beta.types.DeleteEngineRequest" + "type": "google.cloud.discoveryengine_v1beta.types.TuneEngineRequest" }, { "name": "name", @@ -3693,13 +5643,13 @@ } ], "resultType": "google.api_core.operation.Operation", - "shortName": "delete_engine" + "shortName": "tune_engine" }, - "description": "Sample for DeleteEngine", - "file": "discoveryengine_v1beta_generated_engine_service_delete_engine_sync.py", + "description": "Sample for TuneEngine", + "file": "discoveryengine_v1beta_generated_engine_service_tune_engine_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1beta_generated_EngineService_DeleteEngine_sync", + "regionTag": "discoveryengine_v1beta_generated_EngineService_TuneEngine_sync", "segments": [ { "end": 55, @@ -3732,7 +5682,7 @@ "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1beta_generated_engine_service_delete_engine_sync.py" + "title": "discoveryengine_v1beta_generated_engine_service_tune_engine_sync.py" }, { "canonical": true, @@ -3742,23 +5692,27 @@ "fullName": "google.cloud.discoveryengine_v1beta.EngineServiceAsyncClient", "shortName": "EngineServiceAsyncClient" }, - "fullName": "google.cloud.discoveryengine_v1beta.EngineServiceAsyncClient.get_engine", + "fullName": "google.cloud.discoveryengine_v1beta.EngineServiceAsyncClient.update_engine", "method": { - "fullName": "google.cloud.discoveryengine.v1beta.EngineService.GetEngine", + "fullName": "google.cloud.discoveryengine.v1beta.EngineService.UpdateEngine", "service": { "fullName": "google.cloud.discoveryengine.v1beta.EngineService", "shortName": "EngineService" }, - "shortName": "GetEngine" + "shortName": "UpdateEngine" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1beta.types.GetEngineRequest" + "type": "google.cloud.discoveryengine_v1beta.types.UpdateEngineRequest" }, { - "name": "name", - "type": "str" + "name": "engine", + "type": "google.cloud.discoveryengine_v1beta.types.Engine" + }, + { + "name": "update_mask", + "type": "google.protobuf.field_mask_pb2.FieldMask" }, { "name": "retry", @@ -3774,21 +5728,21 @@ } ], "resultType": "google.cloud.discoveryengine_v1beta.types.Engine", - "shortName": "get_engine" + "shortName": "update_engine" }, - "description": "Sample for GetEngine", - "file": "discoveryengine_v1beta_generated_engine_service_get_engine_async.py", + "description": "Sample for UpdateEngine", + "file": "discoveryengine_v1beta_generated_engine_service_update_engine_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1beta_generated_EngineService_GetEngine_async", + "regionTag": "discoveryengine_v1beta_generated_EngineService_UpdateEngine_async", "segments": [ { - "end": 51, + "end": 55, "start": 27, "type": "FULL" }, { - "end": 51, + "end": 55, "start": 27, "type": "SHORT" }, @@ -3798,22 +5752,22 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 45, + "end": 49, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 48, - "start": 46, + "end": 52, + "start": 50, "type": "REQUEST_EXECUTION" }, { - "end": 52, - "start": 49, + "end": 56, + "start": 53, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1beta_generated_engine_service_get_engine_async.py" + "title": "discoveryengine_v1beta_generated_engine_service_update_engine_async.py" }, { "canonical": true, @@ -3822,23 +5776,27 @@ "fullName": "google.cloud.discoveryengine_v1beta.EngineServiceClient", "shortName": "EngineServiceClient" }, - "fullName": "google.cloud.discoveryengine_v1beta.EngineServiceClient.get_engine", + "fullName": "google.cloud.discoveryengine_v1beta.EngineServiceClient.update_engine", "method": { - "fullName": "google.cloud.discoveryengine.v1beta.EngineService.GetEngine", + "fullName": "google.cloud.discoveryengine.v1beta.EngineService.UpdateEngine", "service": { "fullName": "google.cloud.discoveryengine.v1beta.EngineService", "shortName": "EngineService" }, - "shortName": "GetEngine" + "shortName": "UpdateEngine" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1beta.types.GetEngineRequest" + "type": "google.cloud.discoveryengine_v1beta.types.UpdateEngineRequest" }, { - "name": "name", - "type": "str" + "name": "engine", + "type": "google.cloud.discoveryengine_v1beta.types.Engine" + }, + { + "name": "update_mask", + "type": "google.protobuf.field_mask_pb2.FieldMask" }, { "name": "retry", @@ -3854,21 +5812,21 @@ } ], "resultType": "google.cloud.discoveryengine_v1beta.types.Engine", - "shortName": "get_engine" + "shortName": "update_engine" }, - "description": "Sample for GetEngine", - "file": "discoveryengine_v1beta_generated_engine_service_get_engine_sync.py", + "description": "Sample for UpdateEngine", + "file": "discoveryengine_v1beta_generated_engine_service_update_engine_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1beta_generated_EngineService_GetEngine_sync", + "regionTag": "discoveryengine_v1beta_generated_EngineService_UpdateEngine_sync", "segments": [ { - "end": 51, + "end": 55, "start": 27, "type": "FULL" }, { - "end": 51, + "end": 55, "start": 27, "type": "SHORT" }, @@ -3878,48 +5836,44 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 45, + "end": 49, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 48, - "start": 46, + "end": 52, + "start": 50, "type": "REQUEST_EXECUTION" }, { - "end": 52, - "start": 49, + "end": 56, + "start": 53, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1beta_generated_engine_service_get_engine_sync.py" + "title": "discoveryengine_v1beta_generated_engine_service_update_engine_sync.py" }, { "canonical": true, "clientMethod": { "async": true, "client": { - "fullName": "google.cloud.discoveryengine_v1beta.EngineServiceAsyncClient", - "shortName": "EngineServiceAsyncClient" + "fullName": "google.cloud.discoveryengine_v1beta.GroundedGenerationServiceAsyncClient", + "shortName": "GroundedGenerationServiceAsyncClient" }, - "fullName": "google.cloud.discoveryengine_v1beta.EngineServiceAsyncClient.list_engines", + "fullName": "google.cloud.discoveryengine_v1beta.GroundedGenerationServiceAsyncClient.check_grounding", "method": { - "fullName": "google.cloud.discoveryengine.v1beta.EngineService.ListEngines", + "fullName": "google.cloud.discoveryengine.v1beta.GroundedGenerationService.CheckGrounding", "service": { - "fullName": "google.cloud.discoveryengine.v1beta.EngineService", - "shortName": "EngineService" + "fullName": "google.cloud.discoveryengine.v1beta.GroundedGenerationService", + "shortName": "GroundedGenerationService" }, - "shortName": "ListEngines" + "shortName": "CheckGrounding" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1beta.types.ListEnginesRequest" - }, - { - "name": "parent", - "type": "str" + "type": "google.cloud.discoveryengine_v1beta.types.CheckGroundingRequest" }, { "name": "retry", @@ -3934,22 +5888,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1beta.services.engine_service.pagers.ListEnginesAsyncPager", - "shortName": "list_engines" + "resultType": "google.cloud.discoveryengine_v1beta.types.CheckGroundingResponse", + "shortName": "check_grounding" }, - "description": "Sample for ListEngines", - "file": "discoveryengine_v1beta_generated_engine_service_list_engines_async.py", + "description": "Sample for CheckGrounding", + "file": "discoveryengine_v1beta_generated_grounded_generation_service_check_grounding_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1beta_generated_EngineService_ListEngines_async", + "regionTag": "discoveryengine_v1beta_generated_GroundedGenerationService_CheckGrounding_async", "segments": [ { - "end": 52, + "end": 51, "start": 27, "type": "FULL" }, { - "end": 52, + "end": 51, "start": 27, "type": "SHORT" }, @@ -3969,37 +5923,33 @@ "type": "REQUEST_EXECUTION" }, { - "end": 53, + "end": 52, "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1beta_generated_engine_service_list_engines_async.py" + "title": "discoveryengine_v1beta_generated_grounded_generation_service_check_grounding_async.py" }, { "canonical": true, "clientMethod": { "client": { - "fullName": "google.cloud.discoveryengine_v1beta.EngineServiceClient", - "shortName": "EngineServiceClient" + "fullName": "google.cloud.discoveryengine_v1beta.GroundedGenerationServiceClient", + "shortName": "GroundedGenerationServiceClient" }, - "fullName": "google.cloud.discoveryengine_v1beta.EngineServiceClient.list_engines", + "fullName": "google.cloud.discoveryengine_v1beta.GroundedGenerationServiceClient.check_grounding", "method": { - "fullName": "google.cloud.discoveryengine.v1beta.EngineService.ListEngines", + "fullName": "google.cloud.discoveryengine.v1beta.GroundedGenerationService.CheckGrounding", "service": { - "fullName": "google.cloud.discoveryengine.v1beta.EngineService", - "shortName": "EngineService" + "fullName": "google.cloud.discoveryengine.v1beta.GroundedGenerationService", + "shortName": "GroundedGenerationService" }, - "shortName": "ListEngines" + "shortName": "CheckGrounding" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1beta.types.ListEnginesRequest" - }, - { - "name": "parent", - "type": "str" + "type": "google.cloud.discoveryengine_v1beta.types.CheckGroundingRequest" }, { "name": "retry", @@ -4014,22 +5964,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1beta.services.engine_service.pagers.ListEnginesPager", - "shortName": "list_engines" + "resultType": "google.cloud.discoveryengine_v1beta.types.CheckGroundingResponse", + "shortName": "check_grounding" }, - "description": "Sample for ListEngines", - "file": "discoveryengine_v1beta_generated_engine_service_list_engines_sync.py", + "description": "Sample for CheckGrounding", + "file": "discoveryengine_v1beta_generated_grounded_generation_service_check_grounding_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1beta_generated_EngineService_ListEngines_sync", + "regionTag": "discoveryengine_v1beta_generated_GroundedGenerationService_CheckGrounding_sync", "segments": [ { - "end": 52, + "end": 51, "start": 27, "type": "FULL" }, { - "end": 52, + "end": 51, "start": 27, "type": "SHORT" }, @@ -4049,42 +5999,34 @@ "type": "REQUEST_EXECUTION" }, { - "end": 53, + "end": 52, "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1beta_generated_engine_service_list_engines_sync.py" + "title": "discoveryengine_v1beta_generated_grounded_generation_service_check_grounding_sync.py" }, { "canonical": true, "clientMethod": { "async": true, "client": { - "fullName": "google.cloud.discoveryengine_v1beta.EngineServiceAsyncClient", - "shortName": "EngineServiceAsyncClient" + "fullName": "google.cloud.discoveryengine_v1beta.RankServiceAsyncClient", + "shortName": "RankServiceAsyncClient" }, - "fullName": "google.cloud.discoveryengine_v1beta.EngineServiceAsyncClient.update_engine", + "fullName": "google.cloud.discoveryengine_v1beta.RankServiceAsyncClient.rank", "method": { - "fullName": "google.cloud.discoveryengine.v1beta.EngineService.UpdateEngine", + "fullName": "google.cloud.discoveryengine.v1beta.RankService.Rank", "service": { - "fullName": "google.cloud.discoveryengine.v1beta.EngineService", - "shortName": "EngineService" + "fullName": "google.cloud.discoveryengine.v1beta.RankService", + "shortName": "RankService" }, - "shortName": "UpdateEngine" + "shortName": "Rank" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1beta.types.UpdateEngineRequest" - }, - { - "name": "engine", - "type": "google.cloud.discoveryengine_v1beta.types.Engine" - }, - { - "name": "update_mask", - "type": "google.protobuf.field_mask_pb2.FieldMask" + "type": "google.cloud.discoveryengine_v1beta.types.RankRequest" }, { "name": "retry", @@ -4099,22 +6041,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1beta.types.Engine", - "shortName": "update_engine" + "resultType": "google.cloud.discoveryengine_v1beta.types.RankResponse", + "shortName": "rank" }, - "description": "Sample for UpdateEngine", - "file": "discoveryengine_v1beta_generated_engine_service_update_engine_async.py", + "description": "Sample for Rank", + "file": "discoveryengine_v1beta_generated_rank_service_rank_async.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1beta_generated_EngineService_UpdateEngine_async", + "regionTag": "discoveryengine_v1beta_generated_RankService_Rank_async", "segments": [ { - "end": 55, + "end": 51, "start": 27, "type": "FULL" }, { - "end": 55, + "end": 51, "start": 27, "type": "SHORT" }, @@ -4124,51 +6066,43 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 49, + "end": 45, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 52, - "start": 50, + "end": 48, + "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 56, - "start": 53, + "end": 52, + "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1beta_generated_engine_service_update_engine_async.py" + "title": "discoveryengine_v1beta_generated_rank_service_rank_async.py" }, { "canonical": true, "clientMethod": { "client": { - "fullName": "google.cloud.discoveryengine_v1beta.EngineServiceClient", - "shortName": "EngineServiceClient" + "fullName": "google.cloud.discoveryengine_v1beta.RankServiceClient", + "shortName": "RankServiceClient" }, - "fullName": "google.cloud.discoveryengine_v1beta.EngineServiceClient.update_engine", + "fullName": "google.cloud.discoveryengine_v1beta.RankServiceClient.rank", "method": { - "fullName": "google.cloud.discoveryengine.v1beta.EngineService.UpdateEngine", + "fullName": "google.cloud.discoveryengine.v1beta.RankService.Rank", "service": { - "fullName": "google.cloud.discoveryengine.v1beta.EngineService", - "shortName": "EngineService" + "fullName": "google.cloud.discoveryengine.v1beta.RankService", + "shortName": "RankService" }, - "shortName": "UpdateEngine" + "shortName": "Rank" }, "parameters": [ { "name": "request", - "type": "google.cloud.discoveryengine_v1beta.types.UpdateEngineRequest" - }, - { - "name": "engine", - "type": "google.cloud.discoveryengine_v1beta.types.Engine" - }, - { - "name": "update_mask", - "type": "google.protobuf.field_mask_pb2.FieldMask" + "type": "google.cloud.discoveryengine_v1beta.types.RankRequest" }, { "name": "retry", @@ -4183,22 +6117,22 @@ "type": "Sequence[Tuple[str, str]" } ], - "resultType": "google.cloud.discoveryengine_v1beta.types.Engine", - "shortName": "update_engine" + "resultType": "google.cloud.discoveryengine_v1beta.types.RankResponse", + "shortName": "rank" }, - "description": "Sample for UpdateEngine", - "file": "discoveryengine_v1beta_generated_engine_service_update_engine_sync.py", + "description": "Sample for Rank", + "file": "discoveryengine_v1beta_generated_rank_service_rank_sync.py", "language": "PYTHON", "origin": "API_DEFINITION", - "regionTag": "discoveryengine_v1beta_generated_EngineService_UpdateEngine_sync", + "regionTag": "discoveryengine_v1beta_generated_RankService_Rank_sync", "segments": [ { - "end": 55, + "end": 51, "start": 27, "type": "FULL" }, { - "end": 55, + "end": 51, "start": 27, "type": "SHORT" }, @@ -4208,22 +6142,22 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 49, + "end": 45, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 52, - "start": 50, + "end": 48, + "start": 46, "type": "REQUEST_EXECUTION" }, { - "end": 56, - "start": 53, + "end": 52, + "start": 49, "type": "RESPONSE_HANDLING" } ], - "title": "discoveryengine_v1beta_generated_engine_service_update_engine_sync.py" + "title": "discoveryengine_v1beta_generated_rank_service_rank_sync.py" }, { "canonical": true, diff --git a/packages/google-cloud-discoveryengine/scripts/fixup_discoveryengine_v1_keywords.py b/packages/google-cloud-discoveryengine/scripts/fixup_discoveryengine_v1_keywords.py index 60415a0ab580..3009b9eb70ed 100644 --- a/packages/google-cloud-discoveryengine/scripts/fixup_discoveryengine_v1_keywords.py +++ b/packages/google-cloud-discoveryengine/scripts/fixup_discoveryengine_v1_keywords.py @@ -43,7 +43,7 @@ class discoveryengineCallTransformer(cst.CSTTransformer): 'batch_verify_target_sites': ('parent', ), 'collect_user_event': ('parent', 'user_event', 'uri', 'ets', ), 'complete_query': ('data_store', 'query', 'query_model', 'user_pseudo_id', 'include_tail_suggestions', ), - 'converse_conversation': ('name', 'query', 'serving_config', 'conversation', 'safe_search', 'user_labels', 'summary_spec', 'filter', ), + 'converse_conversation': ('name', 'query', 'serving_config', 'conversation', 'safe_search', 'user_labels', 'summary_spec', 'filter', 'boost_spec', ), 'create_conversation': ('parent', 'conversation', ), 'create_data_store': ('parent', 'data_store', 'data_store_id', 'create_advanced_site_search', ), 'create_document': ('parent', 'document', 'document_id', ), @@ -66,7 +66,7 @@ class discoveryengineCallTransformer(cst.CSTTransformer): 'get_schema': ('name', ), 'get_site_search_engine': ('name', ), 'get_target_site': ('name', ), - 'import_documents': ('parent', 'inline_source', 'gcs_source', 'bigquery_source', 'error_config', 'reconciliation_mode', 'auto_generate_ids', 'id_field', ), + 'import_documents': ('parent', 'inline_source', 'gcs_source', 'bigquery_source', 'fhir_store_source', 'spanner_source', 'cloud_sql_source', 'firestore_source', 'bigtable_source', 'error_config', 'reconciliation_mode', 'update_mask', 'auto_generate_ids', 'id_field', ), 'import_suggestion_deny_list_entries': ('parent', 'inline_source', 'gcs_source', ), 'import_user_events': ('parent', 'inline_source', 'gcs_source', 'bigquery_source', 'error_config', ), 'list_conversations': ('parent', 'page_size', 'page_token', 'filter', 'order_by', ), @@ -77,11 +77,12 @@ class discoveryengineCallTransformer(cst.CSTTransformer): 'list_target_sites': ('parent', 'page_size', 'page_token', ), 'purge_documents': ('parent', 'filter', 'force', ), 'purge_suggestion_deny_list_entries': ('parent', ), + 'recommend': ('serving_config', 'user_event', 'page_size', 'filter', 'validate_only', 'params', 'user_labels', ), 'recrawl_uris': ('site_search_engine', 'uris', ), - 'search': ('serving_config', 'branch', 'query', 'image_query', 'page_size', 'page_token', 'offset', 'filter', 'canonical_filter', 'order_by', 'user_info', 'facet_specs', 'boost_spec', 'params', 'query_expansion_spec', 'spell_correction_spec', 'user_pseudo_id', 'content_search_spec', 'safe_search', 'user_labels', ), + 'search': ('serving_config', 'branch', 'query', 'image_query', 'page_size', 'page_token', 'offset', 'data_store_specs', 'filter', 'canonical_filter', 'order_by', 'user_info', 'facet_specs', 'boost_spec', 'params', 'query_expansion_spec', 'spell_correction_spec', 'user_pseudo_id', 'content_search_spec', 'safe_search', 'user_labels', ), 'update_conversation': ('conversation', 'update_mask', ), 'update_data_store': ('data_store', 'update_mask', ), - 'update_document': ('document', 'allow_missing', ), + 'update_document': ('document', 'allow_missing', 'update_mask', ), 'update_engine': ('engine', 'update_mask', ), 'update_schema': ('schema', 'allow_missing', ), 'update_target_site': ('target_site', ), diff --git a/packages/google-cloud-discoveryengine/scripts/fixup_discoveryengine_v1alpha_keywords.py b/packages/google-cloud-discoveryengine/scripts/fixup_discoveryengine_v1alpha_keywords.py index 2b7f91b13aab..d85711506fa5 100644 --- a/packages/google-cloud-discoveryengine/scripts/fixup_discoveryengine_v1alpha_keywords.py +++ b/packages/google-cloud-discoveryengine/scripts/fixup_discoveryengine_v1alpha_keywords.py @@ -39,8 +39,10 @@ def partition( class discoveryengineCallTransformer(cst.CSTTransformer): CTRL_PARAMS: Tuple[str] = ('retry', 'timeout', 'metadata') METHOD_TO_PARAMS: Dict[str, Tuple[str]] = { + 'answer_query': ('serving_config', 'query', 'session', 'safety_spec', 'related_questions_spec', 'answer_generation_spec', 'search_spec', 'query_understanding_spec', 'asynchronous_mode', 'user_pseudo_id', ), 'batch_create_target_sites': ('parent', 'requests', ), 'batch_verify_target_sites': ('parent', ), + 'check_grounding': ('grounding_config', 'answer_candidate', 'facts', 'grounding_spec', ), 'collect_user_event': ('parent', 'user_event', 'uri', 'ets', ), 'complete_query': ('data_store', 'query', 'query_model', 'user_pseudo_id', 'include_tail_suggestions', ), 'converse_conversation': ('name', 'query', 'serving_config', 'conversation', 'safe_search', 'user_labels', 'summary_spec', 'filter', 'boost_spec', ), @@ -49,29 +51,35 @@ class discoveryengineCallTransformer(cst.CSTTransformer): 'create_document': ('parent', 'document', 'document_id', ), 'create_engine': ('parent', 'engine', 'engine_id', ), 'create_schema': ('parent', 'schema', 'schema_id', ), + 'create_session': ('parent', 'session', ), 'create_target_site': ('parent', 'target_site', ), 'delete_conversation': ('name', ), 'delete_data_store': ('name', ), 'delete_document': ('name', ), 'delete_engine': ('name', ), 'delete_schema': ('name', ), + 'delete_session': ('name', ), 'delete_target_site': ('name', ), 'disable_advanced_site_search': ('site_search_engine', ), 'enable_advanced_site_search': ('site_search_engine', ), 'estimate_data_size': ('location', 'website_data_source', 'file_data_source', ), 'fetch_domain_verification_status': ('site_search_engine', 'page_size', 'page_token', ), 'get_acl_config': ('name', ), + 'get_answer': ('name', ), 'get_chunk': ('name', ), 'get_conversation': ('name', ), 'get_data_store': ('name', ), 'get_document': ('name', ), 'get_document_processing_config': ('name', ), 'get_engine': ('name', ), + 'get_processed_document': ('name', 'processed_document_type', 'processed_document_format', ), + 'get_project': ('name', ), 'get_schema': ('name', ), 'get_serving_config': ('name', ), + 'get_session': ('name', ), 'get_site_search_engine': ('name', ), 'get_target_site': ('name', ), - 'import_documents': ('parent', 'inline_source', 'gcs_source', 'bigquery_source', 'error_config', 'reconciliation_mode', 'auto_generate_ids', 'id_field', ), + 'import_documents': ('parent', 'inline_source', 'gcs_source', 'bigquery_source', 'fhir_store_source', 'spanner_source', 'cloud_sql_source', 'firestore_source', 'bigtable_source', 'error_config', 'reconciliation_mode', 'update_mask', 'auto_generate_ids', 'id_field', ), 'import_suggestion_deny_list_entries': ('parent', 'inline_source', 'gcs_source', ), 'import_user_events': ('parent', 'inline_source', 'gcs_source', 'bigquery_source', 'error_config', ), 'list_chunks': ('parent', 'page_size', 'page_token', ), @@ -81,13 +89,17 @@ class discoveryengineCallTransformer(cst.CSTTransformer): 'list_engines': ('parent', 'page_size', 'page_token', 'filter', ), 'list_schemas': ('parent', 'page_size', 'page_token', ), 'list_serving_configs': ('parent', 'page_size', 'page_token', ), + 'list_sessions': ('parent', 'page_size', 'page_token', 'filter', 'order_by', ), 'list_target_sites': ('parent', 'page_size', 'page_token', ), 'pause_engine': ('name', ), + 'provision_project': ('name', 'accept_data_use_terms', 'data_use_terms_version', ), 'purge_documents': ('parent', 'filter', 'gcs_source', 'error_config', 'force', ), 'purge_suggestion_deny_list_entries': ('parent', ), 'purge_user_events': ('parent', 'filter', 'force', ), + 'rank': ('ranking_config', 'records', 'model', 'top_n', 'query', 'ignore_record_details_in_response', ), 'recommend': ('serving_config', 'user_event', 'page_size', 'filter', 'validate_only', 'params', 'user_labels', ), 'recrawl_uris': ('site_search_engine', 'uris', ), + 'report_consent_change': ('consent_change_action', 'project', 'service_term_id', 'service_term_version', ), 'resume_engine': ('name', ), 'search': ('serving_config', 'branch', 'query', 'image_query', 'page_size', 'page_token', 'offset', 'data_store_specs', 'filter', 'canonical_filter', 'order_by', 'user_info', 'facet_specs', 'boost_spec', 'params', 'query_expansion_spec', 'spell_correction_spec', 'user_pseudo_id', 'content_search_spec', 'embedding_spec', 'ranking_expression', 'safe_search', 'user_labels', 'custom_fine_tuning_spec', ), 'train_custom_model': ('data_store', 'gcs_training_input', 'model_type', 'error_config', ), @@ -100,6 +112,7 @@ class discoveryengineCallTransformer(cst.CSTTransformer): 'update_engine': ('engine', 'update_mask', ), 'update_schema': ('schema', 'allow_missing', ), 'update_serving_config': ('serving_config', 'update_mask', ), + 'update_session': ('session', 'update_mask', ), 'update_target_site': ('target_site', ), 'write_user_event': ('parent', 'user_event', ), } diff --git a/packages/google-cloud-discoveryengine/scripts/fixup_discoveryengine_v1beta_keywords.py b/packages/google-cloud-discoveryengine/scripts/fixup_discoveryengine_v1beta_keywords.py index b32e26eb5d53..0e95dcadf879 100644 --- a/packages/google-cloud-discoveryengine/scripts/fixup_discoveryengine_v1beta_keywords.py +++ b/packages/google-cloud-discoveryengine/scripts/fixup_discoveryengine_v1beta_keywords.py @@ -39,8 +39,10 @@ def partition( class discoveryengineCallTransformer(cst.CSTTransformer): CTRL_PARAMS: Tuple[str] = ('retry', 'timeout', 'metadata') METHOD_TO_PARAMS: Dict[str, Tuple[str]] = { + 'answer_query': ('serving_config', 'query', 'session', 'safety_spec', 'related_questions_spec', 'answer_generation_spec', 'search_spec', 'query_understanding_spec', 'asynchronous_mode', 'user_pseudo_id', ), 'batch_create_target_sites': ('parent', 'requests', ), 'batch_verify_target_sites': ('parent', ), + 'check_grounding': ('grounding_config', 'answer_candidate', 'facts', 'grounding_spec', ), 'collect_user_event': ('parent', 'user_event', 'uri', 'ets', ), 'complete_query': ('data_store', 'query', 'query_model', 'user_pseudo_id', 'include_tail_suggestions', ), 'converse_conversation': ('name', 'query', 'serving_config', 'conversation', 'safe_search', 'user_labels', 'summary_spec', 'filter', 'boost_spec', ), @@ -49,25 +51,29 @@ class discoveryengineCallTransformer(cst.CSTTransformer): 'create_document': ('parent', 'document', 'document_id', ), 'create_engine': ('parent', 'engine', 'engine_id', ), 'create_schema': ('parent', 'schema', 'schema_id', ), + 'create_session': ('parent', 'session', ), 'create_target_site': ('parent', 'target_site', ), 'delete_conversation': ('name', ), 'delete_data_store': ('name', ), 'delete_document': ('name', ), 'delete_engine': ('name', ), 'delete_schema': ('name', ), + 'delete_session': ('name', ), 'delete_target_site': ('name', ), 'disable_advanced_site_search': ('site_search_engine', ), 'enable_advanced_site_search': ('site_search_engine', ), 'fetch_domain_verification_status': ('site_search_engine', 'page_size', 'page_token', ), + 'get_answer': ('name', ), 'get_conversation': ('name', ), 'get_data_store': ('name', ), 'get_document': ('name', ), 'get_engine': ('name', ), 'get_schema': ('name', ), 'get_serving_config': ('name', ), + 'get_session': ('name', ), 'get_site_search_engine': ('name', ), 'get_target_site': ('name', ), - 'import_documents': ('parent', 'inline_source', 'gcs_source', 'bigquery_source', 'error_config', 'reconciliation_mode', 'auto_generate_ids', 'id_field', ), + 'import_documents': ('parent', 'inline_source', 'gcs_source', 'bigquery_source', 'fhir_store_source', 'spanner_source', 'cloud_sql_source', 'firestore_source', 'bigtable_source', 'error_config', 'reconciliation_mode', 'update_mask', 'auto_generate_ids', 'id_field', ), 'import_suggestion_deny_list_entries': ('parent', 'inline_source', 'gcs_source', ), 'import_user_events': ('parent', 'inline_source', 'gcs_source', 'bigquery_source', 'error_config', ), 'list_conversations': ('parent', 'page_size', 'page_token', 'filter', 'order_by', ), @@ -76,19 +82,25 @@ class discoveryengineCallTransformer(cst.CSTTransformer): 'list_engines': ('parent', 'page_size', 'page_token', 'filter', ), 'list_schemas': ('parent', 'page_size', 'page_token', ), 'list_serving_configs': ('parent', 'page_size', 'page_token', ), + 'list_sessions': ('parent', 'page_size', 'page_token', 'filter', 'order_by', ), 'list_target_sites': ('parent', 'page_size', 'page_token', ), + 'pause_engine': ('name', ), 'purge_documents': ('parent', 'filter', 'force', ), 'purge_suggestion_deny_list_entries': ('parent', ), + 'rank': ('ranking_config', 'records', 'model', 'top_n', 'query', 'ignore_record_details_in_response', ), 'recommend': ('serving_config', 'user_event', 'page_size', 'filter', 'validate_only', 'params', 'user_labels', ), 'recrawl_uris': ('site_search_engine', 'uris', ), + 'resume_engine': ('name', ), 'search': ('serving_config', 'branch', 'query', 'image_query', 'page_size', 'page_token', 'offset', 'data_store_specs', 'filter', 'canonical_filter', 'order_by', 'user_info', 'facet_specs', 'boost_spec', 'params', 'query_expansion_spec', 'spell_correction_spec', 'user_pseudo_id', 'content_search_spec', 'embedding_spec', 'ranking_expression', 'safe_search', 'user_labels', ), 'train_custom_model': ('data_store', 'gcs_training_input', 'model_type', 'error_config', ), + 'tune_engine': ('name', ), 'update_conversation': ('conversation', 'update_mask', ), 'update_data_store': ('data_store', 'update_mask', ), - 'update_document': ('document', 'allow_missing', ), + 'update_document': ('document', 'allow_missing', 'update_mask', ), 'update_engine': ('engine', 'update_mask', ), 'update_schema': ('schema', 'allow_missing', ), 'update_serving_config': ('serving_config', 'update_mask', ), + 'update_session': ('session', 'update_mask', ), 'update_target_site': ('target_site', ), 'write_user_event': ('parent', 'user_event', ), } diff --git a/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1/test_conversational_search_service.py b/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1/test_conversational_search_service.py index 3ba53ccc0e18..381b954d09cc 100644 --- a/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1/test_conversational_search_service.py +++ b/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1/test_conversational_search_service.py @@ -3596,6 +3596,12 @@ def test_create_conversation_rest(request_type): "title": "title_value", "document": "document_value", "uri": "uri_value", + "chunk_contents": [ + { + "content": "content_value", + "page_identifier": "page_identifier_value", + } + ], } ], }, @@ -4262,6 +4268,12 @@ def test_update_conversation_rest(request_type): "title": "title_value", "document": "document_value", "uri": "uri_value", + "chunk_contents": [ + { + "content": "content_value", + "page_identifier": "page_identifier_value", + } + ], } ], }, diff --git a/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1/test_data_store_service.py b/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1/test_data_store_service.py index 480820a4b940..b2faf836eb39 100644 --- a/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1/test_data_store_service.py +++ b/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1/test_data_store_service.py @@ -47,6 +47,7 @@ from google.protobuf import empty_pb2 # type: ignore from google.protobuf import field_mask_pb2 # type: ignore from google.protobuf import json_format +from google.protobuf import struct_pb2 # type: ignore from google.protobuf import timestamp_pb2 # type: ignore import grpc from grpc.experimental import aio @@ -65,7 +66,7 @@ from google.cloud.discoveryengine_v1.types import common from google.cloud.discoveryengine_v1.types import data_store from google.cloud.discoveryengine_v1.types import data_store as gcd_data_store -from google.cloud.discoveryengine_v1.types import data_store_service +from google.cloud.discoveryengine_v1.types import data_store_service, schema def client_cert_source_callback(): @@ -2910,6 +2911,11 @@ def test_create_data_store_rest(request_type): "default_schema_id": "default_schema_id_value", "content_config": 1, "create_time": {"seconds": 751, "nanos": 543}, + "starting_schema": { + "struct_schema": {"fields": {}}, + "json_schema": "json_schema_value", + "name": "name_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 @@ -4161,6 +4167,11 @@ def test_update_data_store_rest(request_type): "default_schema_id": "default_schema_id_value", "content_config": 1, "create_time": {"seconds": 751, "nanos": 543}, + "starting_schema": { + "struct_schema": {"fields": {}}, + "json_schema": "json_schema_value", + "name": "name_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 @@ -5154,8 +5165,37 @@ def test_parse_data_store_path(): assert expected == actual +def test_schema_path(): + project = "squid" + location = "clam" + data_store = "whelk" + schema = "octopus" + expected = "projects/{project}/locations/{location}/dataStores/{data_store}/schemas/{schema}".format( + project=project, + location=location, + data_store=data_store, + schema=schema, + ) + actual = DataStoreServiceClient.schema_path(project, location, data_store, schema) + assert expected == actual + + +def test_parse_schema_path(): + expected = { + "project": "oyster", + "location": "nudibranch", + "data_store": "cuttlefish", + "schema": "mussel", + } + path = DataStoreServiceClient.schema_path(**expected) + + # Check that the path construction is reversible. + actual = DataStoreServiceClient.parse_schema_path(path) + assert expected == actual + + def test_common_billing_account_path(): - billing_account = "squid" + billing_account = "winkle" expected = "billingAccounts/{billing_account}".format( billing_account=billing_account, ) @@ -5165,7 +5205,7 @@ def test_common_billing_account_path(): def test_parse_common_billing_account_path(): expected = { - "billing_account": "clam", + "billing_account": "nautilus", } path = DataStoreServiceClient.common_billing_account_path(**expected) @@ -5175,7 +5215,7 @@ def test_parse_common_billing_account_path(): def test_common_folder_path(): - folder = "whelk" + folder = "scallop" expected = "folders/{folder}".format( folder=folder, ) @@ -5185,7 +5225,7 @@ def test_common_folder_path(): def test_parse_common_folder_path(): expected = { - "folder": "octopus", + "folder": "abalone", } path = DataStoreServiceClient.common_folder_path(**expected) @@ -5195,7 +5235,7 @@ def test_parse_common_folder_path(): def test_common_organization_path(): - organization = "oyster" + organization = "squid" expected = "organizations/{organization}".format( organization=organization, ) @@ -5205,7 +5245,7 @@ def test_common_organization_path(): def test_parse_common_organization_path(): expected = { - "organization": "nudibranch", + "organization": "clam", } path = DataStoreServiceClient.common_organization_path(**expected) @@ -5215,7 +5255,7 @@ def test_parse_common_organization_path(): def test_common_project_path(): - project = "cuttlefish" + project = "whelk" expected = "projects/{project}".format( project=project, ) @@ -5225,7 +5265,7 @@ def test_common_project_path(): def test_parse_common_project_path(): expected = { - "project": "mussel", + "project": "octopus", } path = DataStoreServiceClient.common_project_path(**expected) @@ -5235,8 +5275,8 @@ def test_parse_common_project_path(): def test_common_location_path(): - project = "winkle" - location = "nautilus" + project = "oyster" + location = "nudibranch" expected = "projects/{project}/locations/{location}".format( project=project, location=location, @@ -5247,8 +5287,8 @@ def test_common_location_path(): def test_parse_common_location_path(): expected = { - "project": "scallop", - "location": "abalone", + "project": "cuttlefish", + "location": "mussel", } path = DataStoreServiceClient.common_location_path(**expected) diff --git a/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1/test_document_service.py b/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1/test_document_service.py index a019d3af7216..cb175117c99e 100644 --- a/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1/test_document_service.py +++ b/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1/test_document_service.py @@ -44,8 +44,10 @@ 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 from google.protobuf import struct_pb2 # type: ignore +from google.protobuf import timestamp_pb2 # type: ignore from google.type import date_pb2 # type: ignore import grpc from grpc.experimental import aio @@ -2315,7 +2317,7 @@ def test_update_document(request_type, transport: str = "grpc"): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.update_document), "__call__") as call: # Designate an appropriate return value for the call. - call.return_value = document.Document( + call.return_value = gcd_document.Document( name="name_value", id="id_value", schema_id="schema_id_value", @@ -2331,7 +2333,7 @@ def test_update_document(request_type, transport: str = "grpc"): assert args[0] == request # Establish that the response is the type that we expect. - assert isinstance(response, document.Document) + assert isinstance(response, gcd_document.Document) assert response.name == "name_value" assert response.id == "id_value" assert response.schema_id == "schema_id_value" @@ -2388,7 +2390,7 @@ async def test_update_document_empty_call_async(): with mock.patch.object(type(client.transport.update_document), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( - document.Document( + gcd_document.Document( name="name_value", id="id_value", schema_id="schema_id_value", @@ -2418,7 +2420,7 @@ async def test_update_document_async( with mock.patch.object(type(client.transport.update_document), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( - document.Document( + gcd_document.Document( name="name_value", id="id_value", schema_id="schema_id_value", @@ -2434,7 +2436,7 @@ async def test_update_document_async( assert args[0] == request # Establish that the response is the type that we expect. - assert isinstance(response, document.Document) + assert isinstance(response, gcd_document.Document) assert response.name == "name_value" assert response.id == "id_value" assert response.schema_id == "schema_id_value" @@ -2459,7 +2461,7 @@ def test_update_document_field_headers(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.update_document), "__call__") as call: - call.return_value = document.Document() + call.return_value = gcd_document.Document() client.update_document(request) # Establish that the underlying gRPC stub method was called. @@ -2489,7 +2491,9 @@ async def test_update_document_field_headers_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.update_document), "__call__") as call: - call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(document.Document()) + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + gcd_document.Document() + ) await client.update_document(request) # Establish that the underlying gRPC stub method was called. @@ -2505,6 +2509,146 @@ async def test_update_document_field_headers_async(): ) in kw["metadata"] +def test_update_document_flattened(): + client = DocumentServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.update_document), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = gcd_document.Document() + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.update_document( + document=gcd_document.Document( + struct_data=struct_pb2.Struct( + fields={ + "key_value": struct_pb2.Value( + null_value=struct_pb2.NullValue.NULL_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].document + mock_val = gcd_document.Document( + struct_data=struct_pb2.Struct( + fields={ + "key_value": struct_pb2.Value( + null_value=struct_pb2.NullValue.NULL_VALUE + ) + } + ) + ) + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val + + +def test_update_document_flattened_error(): + client = DocumentServiceClient( + 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_document( + document_service.UpdateDocumentRequest(), + document=gcd_document.Document( + struct_data=struct_pb2.Struct( + fields={ + "key_value": struct_pb2.Value( + null_value=struct_pb2.NullValue.NULL_VALUE + ) + } + ) + ), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + +@pytest.mark.asyncio +async def test_update_document_flattened_async(): + client = DocumentServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.update_document), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = gcd_document.Document() + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + gcd_document.Document() + ) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.update_document( + document=gcd_document.Document( + struct_data=struct_pb2.Struct( + fields={ + "key_value": struct_pb2.Value( + null_value=struct_pb2.NullValue.NULL_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].document + mock_val = gcd_document.Document( + struct_data=struct_pb2.Struct( + fields={ + "key_value": struct_pb2.Value( + null_value=struct_pb2.NullValue.NULL_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_document_flattened_error_async(): + client = DocumentServiceAsyncClient( + 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_document( + document_service.UpdateDocumentRequest(), + document=gcd_document.Document( + struct_data=struct_pb2.Struct( + fields={ + "key_value": struct_pb2.Value( + null_value=struct_pb2.NullValue.NULL_VALUE + ) + } + ) + ), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + @pytest.mark.parametrize( "request_type", [ @@ -3814,6 +3958,7 @@ def test_create_document_rest(request_type): }, "parent_document_id": "parent_document_id_value", "derived_struct_data": {}, + "index_time": {"seconds": 751, "nanos": 543}, } # 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 @@ -4222,6 +4367,7 @@ def test_update_document_rest(request_type): }, "parent_document_id": "parent_document_id_value", "derived_struct_data": {}, + "index_time": {"seconds": 751, "nanos": 543}, } # 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 @@ -4295,7 +4441,7 @@ def get_message_fields(field): # 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 = document.Document( + return_value = gcd_document.Document( name="name_value", id="id_value", schema_id="schema_id_value", @@ -4307,7 +4453,7 @@ def get_message_fields(field): response_value = Response() response_value.status_code = 200 # Convert return value to protobuf type - return_value = document.Document.pb(return_value) + return_value = gcd_document.Document.pb(return_value) json_return_value = json_format.MessageToJson(return_value) response_value._content = json_return_value.encode("UTF-8") @@ -4315,7 +4461,7 @@ def get_message_fields(field): response = client.update_document(request) # Establish that the response is the type that we expect. - assert isinstance(response, document.Document) + assert isinstance(response, gcd_document.Document) assert response.name == "name_value" assert response.id == "id_value" assert response.schema_id == "schema_id_value" @@ -4347,7 +4493,12 @@ def test_update_document_rest_required_fields( credentials=ga_credentials.AnonymousCredentials() ).update_document._get_unset_required_fields(jsonified_request) # Check that path parameters and body parameters are not mixing in. - assert not set(unset_fields) - set(("allow_missing",)) + assert not set(unset_fields) - set( + ( + "allow_missing", + "update_mask", + ) + ) jsonified_request.update(unset_fields) # verify required fields with non-default values are left alone @@ -4359,7 +4510,7 @@ def test_update_document_rest_required_fields( request = request_type(**request_init) # Designate an appropriate value for the returned response. - return_value = document.Document() + return_value = gcd_document.Document() # 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 @@ -4381,7 +4532,7 @@ def test_update_document_rest_required_fields( response_value.status_code = 200 # Convert return value to protobuf type - return_value = document.Document.pb(return_value) + return_value = gcd_document.Document.pb(return_value) json_return_value = json_format.MessageToJson(return_value) response_value._content = json_return_value.encode("UTF-8") @@ -4400,7 +4551,15 @@ def test_update_document_rest_unset_required_fields(): ) unset_fields = transport.update_document._get_unset_required_fields({}) - assert set(unset_fields) == (set(("allowMissing",)) & set(("document",))) + assert set(unset_fields) == ( + set( + ( + "allowMissing", + "updateMask", + ) + ) + & set(("document",)) + ) @pytest.mark.parametrize("null_interceptor", [True, False]) @@ -4436,7 +4595,9 @@ def test_update_document_rest_interceptors(null_interceptor): req.return_value = Response() req.return_value.status_code = 200 req.return_value.request = PreparedRequest() - req.return_value._content = document.Document.to_json(document.Document()) + req.return_value._content = gcd_document.Document.to_json( + gcd_document.Document() + ) request = document_service.UpdateDocumentRequest() metadata = [ @@ -4444,7 +4605,7 @@ def test_update_document_rest_interceptors(null_interceptor): ("cephalopod", "squid"), ] pre.return_value = request, metadata - post.return_value = document.Document() + post.return_value = gcd_document.Document() client.update_document( request, @@ -4486,6 +4647,85 @@ def test_update_document_rest_bad_request( client.update_document(request) +def test_update_document_rest_flattened(): + client = DocumentServiceClient( + 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 = gcd_document.Document() + + # get arguments that satisfy an http rule for this method + sample_request = { + "document": { + "name": "projects/sample1/locations/sample2/dataStores/sample3/branches/sample4/documents/sample5" + } + } + + # get truthy value for each flattened field + mock_args = dict( + document=gcd_document.Document( + struct_data=struct_pb2.Struct( + fields={ + "key_value": struct_pb2.Value( + null_value=struct_pb2.NullValue.NULL_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 = gcd_document.Document.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_document(**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/v1/{document.name=projects/*/locations/*/dataStores/*/branches/*/documents/*}" + % client.transport._host, + args[1], + ) + + +def test_update_document_rest_flattened_error(transport: str = "rest"): + client = DocumentServiceClient( + 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_document( + document_service.UpdateDocumentRequest(), + document=gcd_document.Document( + struct_data=struct_pb2.Struct( + fields={ + "key_value": struct_pb2.Value( + null_value=struct_pb2.NullValue.NULL_VALUE + ) + } + ) + ), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + def test_update_document_rest_error(): client = DocumentServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest" @@ -5851,8 +6091,39 @@ def test_parse_document_path(): assert expected == actual +def test_fhir_store_path(): + project = "cuttlefish" + location = "mussel" + dataset = "winkle" + fhir_store = "nautilus" + expected = "projects/{project}/locations/{location}/datasets/{dataset}/fhirStores/{fhir_store}".format( + project=project, + location=location, + dataset=dataset, + fhir_store=fhir_store, + ) + actual = DocumentServiceClient.fhir_store_path( + project, location, dataset, fhir_store + ) + assert expected == actual + + +def test_parse_fhir_store_path(): + expected = { + "project": "scallop", + "location": "abalone", + "dataset": "squid", + "fhir_store": "clam", + } + path = DocumentServiceClient.fhir_store_path(**expected) + + # Check that the path construction is reversible. + actual = DocumentServiceClient.parse_fhir_store_path(path) + assert expected == actual + + def test_common_billing_account_path(): - billing_account = "cuttlefish" + billing_account = "whelk" expected = "billingAccounts/{billing_account}".format( billing_account=billing_account, ) @@ -5862,7 +6133,7 @@ def test_common_billing_account_path(): def test_parse_common_billing_account_path(): expected = { - "billing_account": "mussel", + "billing_account": "octopus", } path = DocumentServiceClient.common_billing_account_path(**expected) @@ -5872,7 +6143,7 @@ def test_parse_common_billing_account_path(): def test_common_folder_path(): - folder = "winkle" + folder = "oyster" expected = "folders/{folder}".format( folder=folder, ) @@ -5882,7 +6153,7 @@ def test_common_folder_path(): def test_parse_common_folder_path(): expected = { - "folder": "nautilus", + "folder": "nudibranch", } path = DocumentServiceClient.common_folder_path(**expected) @@ -5892,7 +6163,7 @@ def test_parse_common_folder_path(): def test_common_organization_path(): - organization = "scallop" + organization = "cuttlefish" expected = "organizations/{organization}".format( organization=organization, ) @@ -5902,7 +6173,7 @@ def test_common_organization_path(): def test_parse_common_organization_path(): expected = { - "organization": "abalone", + "organization": "mussel", } path = DocumentServiceClient.common_organization_path(**expected) @@ -5912,7 +6183,7 @@ def test_parse_common_organization_path(): def test_common_project_path(): - project = "squid" + project = "winkle" expected = "projects/{project}".format( project=project, ) @@ -5922,7 +6193,7 @@ def test_common_project_path(): def test_parse_common_project_path(): expected = { - "project": "clam", + "project": "nautilus", } path = DocumentServiceClient.common_project_path(**expected) @@ -5932,8 +6203,8 @@ def test_parse_common_project_path(): def test_common_location_path(): - project = "whelk" - location = "octopus" + project = "scallop" + location = "abalone" expected = "projects/{project}/locations/{location}".format( project=project, location=location, @@ -5944,8 +6215,8 @@ def test_common_location_path(): def test_parse_common_location_path(): expected = { - "project": "oyster", - "location": "nudibranch", + "project": "squid", + "location": "clam", } path = DocumentServiceClient.common_location_path(**expected) diff --git a/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1/test_recommendation_service.py b/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1/test_recommendation_service.py new file mode 100644 index 000000000000..6b7220d97d78 --- /dev/null +++ b/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1/test_recommendation_service.py @@ -0,0 +1,2847 @@ +# -*- 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 +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 duration_pb2 # type: ignore +from google.protobuf import json_format +from google.protobuf import struct_pb2 # type: ignore +from google.protobuf import timestamp_pb2 # type: ignore +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.discoveryengine_v1.services.recommendation_service import ( + RecommendationServiceAsyncClient, + RecommendationServiceClient, + transports, +) +from google.cloud.discoveryengine_v1.types import ( + common, + recommendation_service, + user_event, +) + + +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 RecommendationServiceClient._get_default_mtls_endpoint(None) is None + assert ( + RecommendationServiceClient._get_default_mtls_endpoint(api_endpoint) + == api_mtls_endpoint + ) + assert ( + RecommendationServiceClient._get_default_mtls_endpoint(api_mtls_endpoint) + == api_mtls_endpoint + ) + assert ( + RecommendationServiceClient._get_default_mtls_endpoint(sandbox_endpoint) + == sandbox_mtls_endpoint + ) + assert ( + RecommendationServiceClient._get_default_mtls_endpoint(sandbox_mtls_endpoint) + == sandbox_mtls_endpoint + ) + assert ( + RecommendationServiceClient._get_default_mtls_endpoint(non_googleapi) + == non_googleapi + ) + + +def test__read_environment_variables(): + assert RecommendationServiceClient._read_environment_variables() == ( + False, + "auto", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "true"}): + assert RecommendationServiceClient._read_environment_variables() == ( + True, + "auto", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "false"}): + assert RecommendationServiceClient._read_environment_variables() == ( + False, + "auto", + None, + ) + + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"} + ): + with pytest.raises(ValueError) as excinfo: + RecommendationServiceClient._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 RecommendationServiceClient._read_environment_variables() == ( + False, + "never", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): + assert RecommendationServiceClient._read_environment_variables() == ( + False, + "always", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "auto"}): + assert RecommendationServiceClient._read_environment_variables() == ( + False, + "auto", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "Unsupported"}): + with pytest.raises(MutualTLSChannelError) as excinfo: + RecommendationServiceClient._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 RecommendationServiceClient._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 RecommendationServiceClient._get_client_cert_source(None, False) is None + assert ( + RecommendationServiceClient._get_client_cert_source( + mock_provided_cert_source, False + ) + is None + ) + assert ( + RecommendationServiceClient._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 ( + RecommendationServiceClient._get_client_cert_source(None, True) + is mock_default_cert_source + ) + assert ( + RecommendationServiceClient._get_client_cert_source( + mock_provided_cert_source, "true" + ) + is mock_provided_cert_source + ) + + +@mock.patch.object( + RecommendationServiceClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(RecommendationServiceClient), +) +@mock.patch.object( + RecommendationServiceAsyncClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(RecommendationServiceAsyncClient), +) +def test__get_api_endpoint(): + api_override = "foo.com" + mock_client_cert_source = mock.Mock() + default_universe = RecommendationServiceClient._DEFAULT_UNIVERSE + default_endpoint = RecommendationServiceClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=default_universe + ) + mock_universe = "bar.com" + mock_endpoint = RecommendationServiceClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=mock_universe + ) + + assert ( + RecommendationServiceClient._get_api_endpoint( + api_override, mock_client_cert_source, default_universe, "always" + ) + == api_override + ) + assert ( + RecommendationServiceClient._get_api_endpoint( + None, mock_client_cert_source, default_universe, "auto" + ) + == RecommendationServiceClient.DEFAULT_MTLS_ENDPOINT + ) + assert ( + RecommendationServiceClient._get_api_endpoint( + None, None, default_universe, "auto" + ) + == default_endpoint + ) + assert ( + RecommendationServiceClient._get_api_endpoint( + None, None, default_universe, "always" + ) + == RecommendationServiceClient.DEFAULT_MTLS_ENDPOINT + ) + assert ( + RecommendationServiceClient._get_api_endpoint( + None, mock_client_cert_source, default_universe, "always" + ) + == RecommendationServiceClient.DEFAULT_MTLS_ENDPOINT + ) + assert ( + RecommendationServiceClient._get_api_endpoint( + None, None, mock_universe, "never" + ) + == mock_endpoint + ) + assert ( + RecommendationServiceClient._get_api_endpoint( + None, None, default_universe, "never" + ) + == default_endpoint + ) + + with pytest.raises(MutualTLSChannelError) as excinfo: + RecommendationServiceClient._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 ( + RecommendationServiceClient._get_universe_domain( + client_universe_domain, universe_domain_env + ) + == client_universe_domain + ) + assert ( + RecommendationServiceClient._get_universe_domain(None, universe_domain_env) + == universe_domain_env + ) + assert ( + RecommendationServiceClient._get_universe_domain(None, None) + == RecommendationServiceClient._DEFAULT_UNIVERSE + ) + + with pytest.raises(ValueError) as excinfo: + RecommendationServiceClient._get_universe_domain("", None) + assert str(excinfo.value) == "Universe Domain cannot be an empty string." + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name", + [ + ( + RecommendationServiceClient, + transports.RecommendationServiceGrpcTransport, + "grpc", + ), + ( + RecommendationServiceClient, + transports.RecommendationServiceRestTransport, + "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", + [ + (RecommendationServiceClient, "grpc"), + (RecommendationServiceAsyncClient, "grpc_asyncio"), + (RecommendationServiceClient, "rest"), + ], +) +def test_recommendation_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 == ( + "discoveryengine.googleapis.com:443" + if transport_name in ["grpc", "grpc_asyncio"] + else "https://discoveryengine.googleapis.com" + ) + + +@pytest.mark.parametrize( + "transport_class,transport_name", + [ + (transports.RecommendationServiceGrpcTransport, "grpc"), + (transports.RecommendationServiceGrpcAsyncIOTransport, "grpc_asyncio"), + (transports.RecommendationServiceRestTransport, "rest"), + ], +) +def test_recommendation_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", + [ + (RecommendationServiceClient, "grpc"), + (RecommendationServiceAsyncClient, "grpc_asyncio"), + (RecommendationServiceClient, "rest"), + ], +) +def test_recommendation_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 == ( + "discoveryengine.googleapis.com:443" + if transport_name in ["grpc", "grpc_asyncio"] + else "https://discoveryengine.googleapis.com" + ) + + +def test_recommendation_service_client_get_transport_class(): + transport = RecommendationServiceClient.get_transport_class() + available_transports = [ + transports.RecommendationServiceGrpcTransport, + transports.RecommendationServiceRestTransport, + ] + assert transport in available_transports + + transport = RecommendationServiceClient.get_transport_class("grpc") + assert transport == transports.RecommendationServiceGrpcTransport + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name", + [ + ( + RecommendationServiceClient, + transports.RecommendationServiceGrpcTransport, + "grpc", + ), + ( + RecommendationServiceAsyncClient, + transports.RecommendationServiceGrpcAsyncIOTransport, + "grpc_asyncio", + ), + ( + RecommendationServiceClient, + transports.RecommendationServiceRestTransport, + "rest", + ), + ], +) +@mock.patch.object( + RecommendationServiceClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(RecommendationServiceClient), +) +@mock.patch.object( + RecommendationServiceAsyncClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(RecommendationServiceAsyncClient), +) +def test_recommendation_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(RecommendationServiceClient, "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(RecommendationServiceClient, "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", + [ + ( + RecommendationServiceClient, + transports.RecommendationServiceGrpcTransport, + "grpc", + "true", + ), + ( + RecommendationServiceAsyncClient, + transports.RecommendationServiceGrpcAsyncIOTransport, + "grpc_asyncio", + "true", + ), + ( + RecommendationServiceClient, + transports.RecommendationServiceGrpcTransport, + "grpc", + "false", + ), + ( + RecommendationServiceAsyncClient, + transports.RecommendationServiceGrpcAsyncIOTransport, + "grpc_asyncio", + "false", + ), + ( + RecommendationServiceClient, + transports.RecommendationServiceRestTransport, + "rest", + "true", + ), + ( + RecommendationServiceClient, + transports.RecommendationServiceRestTransport, + "rest", + "false", + ), + ], +) +@mock.patch.object( + RecommendationServiceClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(RecommendationServiceClient), +) +@mock.patch.object( + RecommendationServiceAsyncClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(RecommendationServiceAsyncClient), +) +@mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "auto"}) +def test_recommendation_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", [RecommendationServiceClient, RecommendationServiceAsyncClient] +) +@mock.patch.object( + RecommendationServiceClient, + "DEFAULT_ENDPOINT", + modify_default_endpoint(RecommendationServiceClient), +) +@mock.patch.object( + RecommendationServiceAsyncClient, + "DEFAULT_ENDPOINT", + modify_default_endpoint(RecommendationServiceAsyncClient), +) +def test_recommendation_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", [RecommendationServiceClient, RecommendationServiceAsyncClient] +) +@mock.patch.object( + RecommendationServiceClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(RecommendationServiceClient), +) +@mock.patch.object( + RecommendationServiceAsyncClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(RecommendationServiceAsyncClient), +) +def test_recommendation_service_client_client_api_endpoint(client_class): + mock_client_cert_source = client_cert_source_callback + api_override = "foo.com" + default_universe = RecommendationServiceClient._DEFAULT_UNIVERSE + default_endpoint = RecommendationServiceClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=default_universe + ) + mock_universe = "bar.com" + mock_endpoint = RecommendationServiceClient._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", + [ + ( + RecommendationServiceClient, + transports.RecommendationServiceGrpcTransport, + "grpc", + ), + ( + RecommendationServiceAsyncClient, + transports.RecommendationServiceGrpcAsyncIOTransport, + "grpc_asyncio", + ), + ( + RecommendationServiceClient, + transports.RecommendationServiceRestTransport, + "rest", + ), + ], +) +def test_recommendation_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", + [ + ( + RecommendationServiceClient, + transports.RecommendationServiceGrpcTransport, + "grpc", + grpc_helpers, + ), + ( + RecommendationServiceAsyncClient, + transports.RecommendationServiceGrpcAsyncIOTransport, + "grpc_asyncio", + grpc_helpers_async, + ), + ( + RecommendationServiceClient, + transports.RecommendationServiceRestTransport, + "rest", + None, + ), + ], +) +def test_recommendation_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_recommendation_service_client_client_options_from_dict(): + with mock.patch( + "google.cloud.discoveryengine_v1.services.recommendation_service.transports.RecommendationServiceGrpcTransport.__init__" + ) as grpc_transport: + grpc_transport.return_value = None + client = RecommendationServiceClient( + 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", + [ + ( + RecommendationServiceClient, + transports.RecommendationServiceGrpcTransport, + "grpc", + grpc_helpers, + ), + ( + RecommendationServiceAsyncClient, + transports.RecommendationServiceGrpcAsyncIOTransport, + "grpc_asyncio", + grpc_helpers_async, + ), + ], +) +def test_recommendation_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( + "discoveryengine.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="discoveryengine.googleapis.com", + ssl_credentials=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + +@pytest.mark.parametrize( + "request_type", + [ + recommendation_service.RecommendRequest, + dict, + ], +) +def test_recommend(request_type, transport: str = "grpc"): + client = RecommendationServiceClient( + 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.recommend), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = recommendation_service.RecommendResponse( + attribution_token="attribution_token_value", + missing_ids=["missing_ids_value"], + validate_only=True, + ) + response = client.recommend(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = recommendation_service.RecommendRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, recommendation_service.RecommendResponse) + assert response.attribution_token == "attribution_token_value" + assert response.missing_ids == ["missing_ids_value"] + assert response.validate_only is True + + +def test_recommend_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 = RecommendationServiceClient( + 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.recommend), "__call__") as call: + client.recommend() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == recommendation_service.RecommendRequest() + + +def test_recommend_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 = RecommendationServiceClient( + 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 = recommendation_service.RecommendRequest( + serving_config="serving_config_value", + filter="filter_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.recommend), "__call__") as call: + client.recommend(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == recommendation_service.RecommendRequest( + serving_config="serving_config_value", + filter="filter_value", + ) + + +@pytest.mark.asyncio +async def test_recommend_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 = RecommendationServiceAsyncClient( + 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.recommend), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + recommendation_service.RecommendResponse( + attribution_token="attribution_token_value", + missing_ids=["missing_ids_value"], + validate_only=True, + ) + ) + response = await client.recommend() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == recommendation_service.RecommendRequest() + + +@pytest.mark.asyncio +async def test_recommend_async( + transport: str = "grpc_asyncio", + request_type=recommendation_service.RecommendRequest, +): + client = RecommendationServiceAsyncClient( + 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.recommend), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + recommendation_service.RecommendResponse( + attribution_token="attribution_token_value", + missing_ids=["missing_ids_value"], + validate_only=True, + ) + ) + response = await client.recommend(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = recommendation_service.RecommendRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, recommendation_service.RecommendResponse) + assert response.attribution_token == "attribution_token_value" + assert response.missing_ids == ["missing_ids_value"] + assert response.validate_only is True + + +@pytest.mark.asyncio +async def test_recommend_async_from_dict(): + await test_recommend_async(request_type=dict) + + +def test_recommend_field_headers(): + client = RecommendationServiceClient( + 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 = recommendation_service.RecommendRequest() + + request.serving_config = "serving_config_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.recommend), "__call__") as call: + call.return_value = recommendation_service.RecommendResponse() + client.recommend(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", + "serving_config=serving_config_value", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_recommend_field_headers_async(): + client = RecommendationServiceAsyncClient( + 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 = recommendation_service.RecommendRequest() + + request.serving_config = "serving_config_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.recommend), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + recommendation_service.RecommendResponse() + ) + await client.recommend(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", + "serving_config=serving_config_value", + ) in kw["metadata"] + + +@pytest.mark.parametrize( + "request_type", + [ + recommendation_service.RecommendRequest, + dict, + ], +) +def test_recommend_rest(request_type): + client = RecommendationServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = { + "serving_config": "projects/sample1/locations/sample2/dataStores/sample3/servingConfigs/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 = recommendation_service.RecommendResponse( + attribution_token="attribution_token_value", + missing_ids=["missing_ids_value"], + validate_only=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 = recommendation_service.RecommendResponse.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.recommend(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, recommendation_service.RecommendResponse) + assert response.attribution_token == "attribution_token_value" + assert response.missing_ids == ["missing_ids_value"] + assert response.validate_only is True + + +def test_recommend_rest_required_fields( + request_type=recommendation_service.RecommendRequest, +): + transport_class = transports.RecommendationServiceRestTransport + + request_init = {} + request_init["serving_config"] = "" + 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() + ).recommend._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + jsonified_request["servingConfig"] = "serving_config_value" + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).recommend._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + assert "servingConfig" in jsonified_request + assert jsonified_request["servingConfig"] == "serving_config_value" + + client = RecommendationServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = recommendation_service.RecommendResponse() + # 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 = recommendation_service.RecommendResponse.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.recommend(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_recommend_rest_unset_required_fields(): + transport = transports.RecommendationServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.recommend._get_unset_required_fields({}) + assert set(unset_fields) == ( + set(()) + & set( + ( + "servingConfig", + "userEvent", + ) + ) + ) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_recommend_rest_interceptors(null_interceptor): + transport = transports.RecommendationServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.RecommendationServiceRestInterceptor(), + ) + client = RecommendationServiceClient(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.RecommendationServiceRestInterceptor, "post_recommend" + ) as post, mock.patch.object( + transports.RecommendationServiceRestInterceptor, "pre_recommend" + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = recommendation_service.RecommendRequest.pb( + recommendation_service.RecommendRequest() + ) + 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 = recommendation_service.RecommendResponse.to_json( + recommendation_service.RecommendResponse() + ) + + request = recommendation_service.RecommendRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = recommendation_service.RecommendResponse() + + client.recommend( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_recommend_rest_bad_request( + transport: str = "rest", request_type=recommendation_service.RecommendRequest +): + client = RecommendationServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = { + "serving_config": "projects/sample1/locations/sample2/dataStores/sample3/servingConfigs/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.recommend(request) + + +def test_recommend_rest_error(): + client = RecommendationServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + +def test_credentials_transport_error(): + # It is an error to provide credentials and a transport instance. + transport = transports.RecommendationServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + with pytest.raises(ValueError): + client = RecommendationServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # It is an error to provide a credentials file and a transport instance. + transport = transports.RecommendationServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + with pytest.raises(ValueError): + client = RecommendationServiceClient( + client_options={"credentials_file": "credentials.json"}, + transport=transport, + ) + + # It is an error to provide an api_key and a transport instance. + transport = transports.RecommendationServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + options = client_options.ClientOptions() + options.api_key = "api_key" + with pytest.raises(ValueError): + client = RecommendationServiceClient( + 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 = RecommendationServiceClient( + client_options=options, credentials=ga_credentials.AnonymousCredentials() + ) + + # It is an error to provide scopes and a transport instance. + transport = transports.RecommendationServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + with pytest.raises(ValueError): + client = RecommendationServiceClient( + client_options={"scopes": ["1", "2"]}, + transport=transport, + ) + + +def test_transport_instance(): + # A client may be instantiated with a custom transport instance. + transport = transports.RecommendationServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + client = RecommendationServiceClient(transport=transport) + assert client.transport is transport + + +def test_transport_get_channel(): + # A client may be instantiated with a custom transport instance. + transport = transports.RecommendationServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + channel = transport.grpc_channel + assert channel + + transport = transports.RecommendationServiceGrpcAsyncIOTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + channel = transport.grpc_channel + assert channel + + +@pytest.mark.parametrize( + "transport_class", + [ + transports.RecommendationServiceGrpcTransport, + transports.RecommendationServiceGrpcAsyncIOTransport, + transports.RecommendationServiceRestTransport, + ], +) +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 = RecommendationServiceClient.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 = RecommendationServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + assert isinstance( + client.transport, + transports.RecommendationServiceGrpcTransport, + ) + + +def test_recommendation_service_base_transport_error(): + # Passing both a credentials object and credentials_file should raise an error + with pytest.raises(core_exceptions.DuplicateCredentialArgs): + transport = transports.RecommendationServiceTransport( + credentials=ga_credentials.AnonymousCredentials(), + credentials_file="credentials.json", + ) + + +def test_recommendation_service_base_transport(): + # Instantiate the base transport. + with mock.patch( + "google.cloud.discoveryengine_v1.services.recommendation_service.transports.RecommendationServiceTransport.__init__" + ) as Transport: + Transport.return_value = None + transport = transports.RecommendationServiceTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Every method on the transport should just blindly + # raise NotImplementedError. + methods = ( + "recommend", + "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_recommendation_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.discoveryengine_v1.services.recommendation_service.transports.RecommendationServiceTransport._prep_wrapped_messages" + ) as Transport: + Transport.return_value = None + load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) + transport = transports.RecommendationServiceTransport( + 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_recommendation_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.discoveryengine_v1.services.recommendation_service.transports.RecommendationServiceTransport._prep_wrapped_messages" + ) as Transport: + Transport.return_value = None + adc.return_value = (ga_credentials.AnonymousCredentials(), None) + transport = transports.RecommendationServiceTransport() + adc.assert_called_once() + + +def test_recommendation_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) + RecommendationServiceClient() + 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.RecommendationServiceGrpcTransport, + transports.RecommendationServiceGrpcAsyncIOTransport, + ], +) +def test_recommendation_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.RecommendationServiceGrpcTransport, + transports.RecommendationServiceGrpcAsyncIOTransport, + transports.RecommendationServiceRestTransport, + ], +) +def test_recommendation_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.RecommendationServiceGrpcTransport, grpc_helpers), + (transports.RecommendationServiceGrpcAsyncIOTransport, grpc_helpers_async), + ], +) +def test_recommendation_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( + "discoveryengine.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="discoveryengine.googleapis.com", + ssl_credentials=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + +@pytest.mark.parametrize( + "transport_class", + [ + transports.RecommendationServiceGrpcTransport, + transports.RecommendationServiceGrpcAsyncIOTransport, + ], +) +def test_recommendation_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_recommendation_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.RecommendationServiceRestTransport( + 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_recommendation_service_host_no_port(transport_name): + client = RecommendationServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + client_options=client_options.ClientOptions( + api_endpoint="discoveryengine.googleapis.com" + ), + transport=transport_name, + ) + assert client.transport._host == ( + "discoveryengine.googleapis.com:443" + if transport_name in ["grpc", "grpc_asyncio"] + else "https://discoveryengine.googleapis.com" + ) + + +@pytest.mark.parametrize( + "transport_name", + [ + "grpc", + "grpc_asyncio", + "rest", + ], +) +def test_recommendation_service_host_with_port(transport_name): + client = RecommendationServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + client_options=client_options.ClientOptions( + api_endpoint="discoveryengine.googleapis.com:8000" + ), + transport=transport_name, + ) + assert client.transport._host == ( + "discoveryengine.googleapis.com:8000" + if transport_name in ["grpc", "grpc_asyncio"] + else "https://discoveryengine.googleapis.com:8000" + ) + + +@pytest.mark.parametrize( + "transport_name", + [ + "rest", + ], +) +def test_recommendation_service_client_transport_session_collision(transport_name): + creds1 = ga_credentials.AnonymousCredentials() + creds2 = ga_credentials.AnonymousCredentials() + client1 = RecommendationServiceClient( + credentials=creds1, + transport=transport_name, + ) + client2 = RecommendationServiceClient( + credentials=creds2, + transport=transport_name, + ) + session1 = client1.transport.recommend._session + session2 = client2.transport.recommend._session + assert session1 != session2 + + +def test_recommendation_service_grpc_transport_channel(): + channel = grpc.secure_channel("http://localhost/", grpc.local_channel_credentials()) + + # Check that channel is used if provided. + transport = transports.RecommendationServiceGrpcTransport( + 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_recommendation_service_grpc_asyncio_transport_channel(): + channel = aio.secure_channel("http://localhost/", grpc.local_channel_credentials()) + + # Check that channel is used if provided. + transport = transports.RecommendationServiceGrpcAsyncIOTransport( + 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.RecommendationServiceGrpcTransport, + transports.RecommendationServiceGrpcAsyncIOTransport, + ], +) +def test_recommendation_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.RecommendationServiceGrpcTransport, + transports.RecommendationServiceGrpcAsyncIOTransport, + ], +) +def test_recommendation_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_document_path(): + project = "squid" + location = "clam" + data_store = "whelk" + branch = "octopus" + document = "oyster" + expected = "projects/{project}/locations/{location}/dataStores/{data_store}/branches/{branch}/documents/{document}".format( + project=project, + location=location, + data_store=data_store, + branch=branch, + document=document, + ) + actual = RecommendationServiceClient.document_path( + project, location, data_store, branch, document + ) + assert expected == actual + + +def test_parse_document_path(): + expected = { + "project": "nudibranch", + "location": "cuttlefish", + "data_store": "mussel", + "branch": "winkle", + "document": "nautilus", + } + path = RecommendationServiceClient.document_path(**expected) + + # Check that the path construction is reversible. + actual = RecommendationServiceClient.parse_document_path(path) + assert expected == actual + + +def test_serving_config_path(): + project = "scallop" + location = "abalone" + data_store = "squid" + serving_config = "clam" + expected = "projects/{project}/locations/{location}/dataStores/{data_store}/servingConfigs/{serving_config}".format( + project=project, + location=location, + data_store=data_store, + serving_config=serving_config, + ) + actual = RecommendationServiceClient.serving_config_path( + project, location, data_store, serving_config + ) + assert expected == actual + + +def test_parse_serving_config_path(): + expected = { + "project": "whelk", + "location": "octopus", + "data_store": "oyster", + "serving_config": "nudibranch", + } + path = RecommendationServiceClient.serving_config_path(**expected) + + # Check that the path construction is reversible. + actual = RecommendationServiceClient.parse_serving_config_path(path) + assert expected == actual + + +def test_common_billing_account_path(): + billing_account = "cuttlefish" + expected = "billingAccounts/{billing_account}".format( + billing_account=billing_account, + ) + actual = RecommendationServiceClient.common_billing_account_path(billing_account) + assert expected == actual + + +def test_parse_common_billing_account_path(): + expected = { + "billing_account": "mussel", + } + path = RecommendationServiceClient.common_billing_account_path(**expected) + + # Check that the path construction is reversible. + actual = RecommendationServiceClient.parse_common_billing_account_path(path) + assert expected == actual + + +def test_common_folder_path(): + folder = "winkle" + expected = "folders/{folder}".format( + folder=folder, + ) + actual = RecommendationServiceClient.common_folder_path(folder) + assert expected == actual + + +def test_parse_common_folder_path(): + expected = { + "folder": "nautilus", + } + path = RecommendationServiceClient.common_folder_path(**expected) + + # Check that the path construction is reversible. + actual = RecommendationServiceClient.parse_common_folder_path(path) + assert expected == actual + + +def test_common_organization_path(): + organization = "scallop" + expected = "organizations/{organization}".format( + organization=organization, + ) + actual = RecommendationServiceClient.common_organization_path(organization) + assert expected == actual + + +def test_parse_common_organization_path(): + expected = { + "organization": "abalone", + } + path = RecommendationServiceClient.common_organization_path(**expected) + + # Check that the path construction is reversible. + actual = RecommendationServiceClient.parse_common_organization_path(path) + assert expected == actual + + +def test_common_project_path(): + project = "squid" + expected = "projects/{project}".format( + project=project, + ) + actual = RecommendationServiceClient.common_project_path(project) + assert expected == actual + + +def test_parse_common_project_path(): + expected = { + "project": "clam", + } + path = RecommendationServiceClient.common_project_path(**expected) + + # Check that the path construction is reversible. + actual = RecommendationServiceClient.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 = RecommendationServiceClient.common_location_path(project, location) + assert expected == actual + + +def test_parse_common_location_path(): + expected = { + "project": "oyster", + "location": "nudibranch", + } + path = RecommendationServiceClient.common_location_path(**expected) + + # Check that the path construction is reversible. + actual = RecommendationServiceClient.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.RecommendationServiceTransport, "_prep_wrapped_messages" + ) as prep: + client = RecommendationServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + client_info=client_info, + ) + prep.assert_called_once_with(client_info) + + with mock.patch.object( + transports.RecommendationServiceTransport, "_prep_wrapped_messages" + ) as prep: + transport_class = RecommendationServiceClient.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 = RecommendationServiceAsyncClient( + 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 = RecommendationServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + request = request_type() + request = json_format.ParseDict( + {"name": "projects/sample1/operations/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.get_operation(request) + + +@pytest.mark.parametrize( + "request_type", + [ + operations_pb2.GetOperationRequest, + dict, + ], +) +def test_get_operation_rest(request_type): + client = RecommendationServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request_init = {"name": "projects/sample1/operations/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.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 = RecommendationServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + request = request_type() + request = json_format.ParseDict({"name": "projects/sample1"}, 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 = RecommendationServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request_init = {"name": "projects/sample1"} + 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 = RecommendationServiceClient( + 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 = RecommendationServiceAsyncClient( + 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 = RecommendationServiceClient( + 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 = RecommendationServiceAsyncClient( + 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 = RecommendationServiceClient( + 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 = RecommendationServiceAsyncClient( + 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 = RecommendationServiceClient( + 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 = RecommendationServiceAsyncClient( + 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 = RecommendationServiceClient( + 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 = RecommendationServiceAsyncClient( + 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 = RecommendationServiceClient( + 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 = RecommendationServiceAsyncClient( + 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 = RecommendationServiceClient( + 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 = RecommendationServiceClient( + 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", + [ + (RecommendationServiceClient, transports.RecommendationServiceGrpcTransport), + ( + RecommendationServiceAsyncClient, + transports.RecommendationServiceGrpcAsyncIOTransport, + ), + ], +) +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-discoveryengine/tests/unit/gapic/discoveryengine_v1/test_search_service.py b/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1/test_search_service.py index 06d0cf3faf00..3dce355d5646 100644 --- a/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1/test_search_service.py +++ b/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1/test_search_service.py @@ -2377,12 +2377,38 @@ def test_parse_branch_path(): assert expected == actual -def test_document_path(): +def test_data_store_path(): project = "winkle" location = "nautilus" data_store = "scallop" - branch = "abalone" - document = "squid" + expected = "projects/{project}/locations/{location}/dataStores/{data_store}".format( + project=project, + location=location, + data_store=data_store, + ) + actual = SearchServiceClient.data_store_path(project, location, data_store) + assert expected == actual + + +def test_parse_data_store_path(): + expected = { + "project": "abalone", + "location": "squid", + "data_store": "clam", + } + path = SearchServiceClient.data_store_path(**expected) + + # Check that the path construction is reversible. + actual = SearchServiceClient.parse_data_store_path(path) + assert expected == actual + + +def test_document_path(): + project = "whelk" + location = "octopus" + data_store = "oyster" + branch = "nudibranch" + document = "cuttlefish" expected = "projects/{project}/locations/{location}/dataStores/{data_store}/branches/{branch}/documents/{document}".format( project=project, location=location, @@ -2398,11 +2424,11 @@ def test_document_path(): def test_parse_document_path(): expected = { - "project": "clam", - "location": "whelk", - "data_store": "octopus", - "branch": "oyster", - "document": "nudibranch", + "project": "mussel", + "location": "winkle", + "data_store": "nautilus", + "branch": "scallop", + "document": "abalone", } path = SearchServiceClient.document_path(**expected) @@ -2412,10 +2438,10 @@ def test_parse_document_path(): def test_serving_config_path(): - project = "cuttlefish" - location = "mussel" - data_store = "winkle" - serving_config = "nautilus" + project = "squid" + location = "clam" + data_store = "whelk" + serving_config = "octopus" expected = "projects/{project}/locations/{location}/dataStores/{data_store}/servingConfigs/{serving_config}".format( project=project, location=location, @@ -2430,10 +2456,10 @@ def test_serving_config_path(): def test_parse_serving_config_path(): expected = { - "project": "scallop", - "location": "abalone", - "data_store": "squid", - "serving_config": "clam", + "project": "oyster", + "location": "nudibranch", + "data_store": "cuttlefish", + "serving_config": "mussel", } path = SearchServiceClient.serving_config_path(**expected) @@ -2443,7 +2469,7 @@ def test_parse_serving_config_path(): def test_common_billing_account_path(): - billing_account = "whelk" + billing_account = "winkle" expected = "billingAccounts/{billing_account}".format( billing_account=billing_account, ) @@ -2453,7 +2479,7 @@ def test_common_billing_account_path(): def test_parse_common_billing_account_path(): expected = { - "billing_account": "octopus", + "billing_account": "nautilus", } path = SearchServiceClient.common_billing_account_path(**expected) @@ -2463,7 +2489,7 @@ def test_parse_common_billing_account_path(): def test_common_folder_path(): - folder = "oyster" + folder = "scallop" expected = "folders/{folder}".format( folder=folder, ) @@ -2473,7 +2499,7 @@ def test_common_folder_path(): def test_parse_common_folder_path(): expected = { - "folder": "nudibranch", + "folder": "abalone", } path = SearchServiceClient.common_folder_path(**expected) @@ -2483,7 +2509,7 @@ def test_parse_common_folder_path(): def test_common_organization_path(): - organization = "cuttlefish" + organization = "squid" expected = "organizations/{organization}".format( organization=organization, ) @@ -2493,7 +2519,7 @@ def test_common_organization_path(): def test_parse_common_organization_path(): expected = { - "organization": "mussel", + "organization": "clam", } path = SearchServiceClient.common_organization_path(**expected) @@ -2503,7 +2529,7 @@ def test_parse_common_organization_path(): def test_common_project_path(): - project = "winkle" + project = "whelk" expected = "projects/{project}".format( project=project, ) @@ -2513,7 +2539,7 @@ def test_common_project_path(): def test_parse_common_project_path(): expected = { - "project": "nautilus", + "project": "octopus", } path = SearchServiceClient.common_project_path(**expected) @@ -2523,8 +2549,8 @@ def test_parse_common_project_path(): def test_common_location_path(): - project = "scallop" - location = "abalone" + project = "oyster" + location = "nudibranch" expected = "projects/{project}/locations/{location}".format( project=project, location=location, @@ -2535,8 +2561,8 @@ def test_common_location_path(): def test_parse_common_location_path(): expected = { - "project": "squid", - "location": "clam", + "project": "cuttlefish", + "location": "mussel", } path = SearchServiceClient.common_location_path(**expected) diff --git a/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1alpha/test_conversational_search_service.py b/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1alpha/test_conversational_search_service.py index d74d95e7aca4..0a4248420a9a 100644 --- a/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1alpha/test_conversational_search_service.py +++ b/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1alpha/test_conversational_search_service.py @@ -57,7 +57,10 @@ search_service, ) from google.cloud.discoveryengine_v1alpha.types import conversation as gcd_conversation +from google.cloud.discoveryengine_v1alpha.types import answer, common from google.cloud.discoveryengine_v1alpha.types import conversation +from google.cloud.discoveryengine_v1alpha.types import session +from google.cloud.discoveryengine_v1alpha.types import session as gcd_session def client_cert_source_callback(): @@ -3253,6 +3256,2141 @@ async def test_list_conversations_async_pages(): assert page_.raw_page.next_page_token == token +@pytest.mark.parametrize( + "request_type", + [ + conversational_search_service.AnswerQueryRequest, + dict, + ], +) +def test_answer_query(request_type, transport: str = "grpc"): + client = ConversationalSearchServiceClient( + 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.answer_query), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = conversational_search_service.AnswerQueryResponse() + response = client.answer_query(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = conversational_search_service.AnswerQueryRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, conversational_search_service.AnswerQueryResponse) + + +def test_answer_query_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 = ConversationalSearchServiceClient( + 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.answer_query), "__call__") as call: + client.answer_query() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == conversational_search_service.AnswerQueryRequest() + + +def test_answer_query_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 = ConversationalSearchServiceClient( + 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 = conversational_search_service.AnswerQueryRequest( + serving_config="serving_config_value", + session="session_value", + user_pseudo_id="user_pseudo_id_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.answer_query), "__call__") as call: + client.answer_query(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == conversational_search_service.AnswerQueryRequest( + serving_config="serving_config_value", + session="session_value", + user_pseudo_id="user_pseudo_id_value", + ) + + +@pytest.mark.asyncio +async def test_answer_query_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 = ConversationalSearchServiceAsyncClient( + 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.answer_query), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + conversational_search_service.AnswerQueryResponse() + ) + response = await client.answer_query() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == conversational_search_service.AnswerQueryRequest() + + +@pytest.mark.asyncio +async def test_answer_query_async( + transport: str = "grpc_asyncio", + request_type=conversational_search_service.AnswerQueryRequest, +): + client = ConversationalSearchServiceAsyncClient( + 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.answer_query), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + conversational_search_service.AnswerQueryResponse() + ) + response = await client.answer_query(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = conversational_search_service.AnswerQueryRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, conversational_search_service.AnswerQueryResponse) + + +@pytest.mark.asyncio +async def test_answer_query_async_from_dict(): + await test_answer_query_async(request_type=dict) + + +def test_answer_query_field_headers(): + client = ConversationalSearchServiceClient( + 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 = conversational_search_service.AnswerQueryRequest() + + request.serving_config = "serving_config_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.answer_query), "__call__") as call: + call.return_value = conversational_search_service.AnswerQueryResponse() + client.answer_query(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", + "serving_config=serving_config_value", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_answer_query_field_headers_async(): + client = ConversationalSearchServiceAsyncClient( + 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 = conversational_search_service.AnswerQueryRequest() + + request.serving_config = "serving_config_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.answer_query), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + conversational_search_service.AnswerQueryResponse() + ) + await client.answer_query(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", + "serving_config=serving_config_value", + ) in kw["metadata"] + + +@pytest.mark.parametrize( + "request_type", + [ + conversational_search_service.GetAnswerRequest, + dict, + ], +) +def test_get_answer(request_type, transport: str = "grpc"): + client = ConversationalSearchServiceClient( + 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_answer), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = answer.Answer( + name="name_value", + state=answer.Answer.State.IN_PROGRESS, + answer_text="answer_text_value", + related_questions=["related_questions_value"], + answer_skipped_reasons=[ + answer.Answer.AnswerSkippedReason.ADVERSARIAL_QUERY_IGNORED + ], + ) + response = client.get_answer(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = conversational_search_service.GetAnswerRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, answer.Answer) + assert response.name == "name_value" + assert response.state == answer.Answer.State.IN_PROGRESS + assert response.answer_text == "answer_text_value" + assert response.related_questions == ["related_questions_value"] + assert response.answer_skipped_reasons == [ + answer.Answer.AnswerSkippedReason.ADVERSARIAL_QUERY_IGNORED + ] + + +def test_get_answer_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 = ConversationalSearchServiceClient( + 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_answer), "__call__") as call: + client.get_answer() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == conversational_search_service.GetAnswerRequest() + + +def test_get_answer_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 = ConversationalSearchServiceClient( + 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 = conversational_search_service.GetAnswerRequest( + name="name_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_answer), "__call__") as call: + client.get_answer(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == conversational_search_service.GetAnswerRequest( + name="name_value", + ) + + +@pytest.mark.asyncio +async def test_get_answer_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 = ConversationalSearchServiceAsyncClient( + 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_answer), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + answer.Answer( + name="name_value", + state=answer.Answer.State.IN_PROGRESS, + answer_text="answer_text_value", + related_questions=["related_questions_value"], + answer_skipped_reasons=[ + answer.Answer.AnswerSkippedReason.ADVERSARIAL_QUERY_IGNORED + ], + ) + ) + response = await client.get_answer() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == conversational_search_service.GetAnswerRequest() + + +@pytest.mark.asyncio +async def test_get_answer_async( + transport: str = "grpc_asyncio", + request_type=conversational_search_service.GetAnswerRequest, +): + client = ConversationalSearchServiceAsyncClient( + 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_answer), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + answer.Answer( + name="name_value", + state=answer.Answer.State.IN_PROGRESS, + answer_text="answer_text_value", + related_questions=["related_questions_value"], + answer_skipped_reasons=[ + answer.Answer.AnswerSkippedReason.ADVERSARIAL_QUERY_IGNORED + ], + ) + ) + response = await client.get_answer(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = conversational_search_service.GetAnswerRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, answer.Answer) + assert response.name == "name_value" + assert response.state == answer.Answer.State.IN_PROGRESS + assert response.answer_text == "answer_text_value" + assert response.related_questions == ["related_questions_value"] + assert response.answer_skipped_reasons == [ + answer.Answer.AnswerSkippedReason.ADVERSARIAL_QUERY_IGNORED + ] + + +@pytest.mark.asyncio +async def test_get_answer_async_from_dict(): + await test_get_answer_async(request_type=dict) + + +def test_get_answer_field_headers(): + client = ConversationalSearchServiceClient( + 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 = conversational_search_service.GetAnswerRequest() + + request.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_answer), "__call__") as call: + call.return_value = answer.Answer() + client.get_answer(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_answer_field_headers_async(): + client = ConversationalSearchServiceAsyncClient( + 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 = conversational_search_service.GetAnswerRequest() + + request.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_answer), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(answer.Answer()) + await client.get_answer(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_answer_flattened(): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_answer), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = answer.Answer() + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.get_answer( + 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_answer_flattened_error(): + client = ConversationalSearchServiceClient( + 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_answer( + conversational_search_service.GetAnswerRequest(), + name="name_value", + ) + + +@pytest.mark.asyncio +async def test_get_answer_flattened_async(): + client = ConversationalSearchServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_answer), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = answer.Answer() + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(answer.Answer()) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.get_answer( + 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_answer_flattened_error_async(): + client = ConversationalSearchServiceAsyncClient( + 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_answer( + conversational_search_service.GetAnswerRequest(), + name="name_value", + ) + + +@pytest.mark.parametrize( + "request_type", + [ + conversational_search_service.CreateSessionRequest, + dict, + ], +) +def test_create_session(request_type, transport: str = "grpc"): + client = ConversationalSearchServiceClient( + 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.create_session), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = gcd_session.Session( + name="name_value", + state=gcd_session.Session.State.IN_PROGRESS, + user_pseudo_id="user_pseudo_id_value", + ) + response = client.create_session(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = conversational_search_service.CreateSessionRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, gcd_session.Session) + assert response.name == "name_value" + assert response.state == gcd_session.Session.State.IN_PROGRESS + assert response.user_pseudo_id == "user_pseudo_id_value" + + +def test_create_session_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 = ConversationalSearchServiceClient( + 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.create_session), "__call__") as call: + client.create_session() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == conversational_search_service.CreateSessionRequest() + + +def test_create_session_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 = ConversationalSearchServiceClient( + 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 = conversational_search_service.CreateSessionRequest( + parent="parent_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.create_session), "__call__") as call: + client.create_session(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == conversational_search_service.CreateSessionRequest( + parent="parent_value", + ) + + +@pytest.mark.asyncio +async def test_create_session_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 = ConversationalSearchServiceAsyncClient( + 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.create_session), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + gcd_session.Session( + name="name_value", + state=gcd_session.Session.State.IN_PROGRESS, + user_pseudo_id="user_pseudo_id_value", + ) + ) + response = await client.create_session() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == conversational_search_service.CreateSessionRequest() + + +@pytest.mark.asyncio +async def test_create_session_async( + transport: str = "grpc_asyncio", + request_type=conversational_search_service.CreateSessionRequest, +): + client = ConversationalSearchServiceAsyncClient( + 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.create_session), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + gcd_session.Session( + name="name_value", + state=gcd_session.Session.State.IN_PROGRESS, + user_pseudo_id="user_pseudo_id_value", + ) + ) + response = await client.create_session(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = conversational_search_service.CreateSessionRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, gcd_session.Session) + assert response.name == "name_value" + assert response.state == gcd_session.Session.State.IN_PROGRESS + assert response.user_pseudo_id == "user_pseudo_id_value" + + +@pytest.mark.asyncio +async def test_create_session_async_from_dict(): + await test_create_session_async(request_type=dict) + + +def test_create_session_field_headers(): + client = ConversationalSearchServiceClient( + 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 = conversational_search_service.CreateSessionRequest() + + request.parent = "parent_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.create_session), "__call__") as call: + call.return_value = gcd_session.Session() + client.create_session(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_create_session_field_headers_async(): + client = ConversationalSearchServiceAsyncClient( + 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 = conversational_search_service.CreateSessionRequest() + + request.parent = "parent_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.create_session), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(gcd_session.Session()) + await client.create_session(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "parent=parent_value", + ) in kw["metadata"] + + +def test_create_session_flattened(): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.create_session), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = gcd_session.Session() + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.create_session( + parent="parent_value", + session=gcd_session.Session(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].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].session + mock_val = gcd_session.Session(name="name_value") + assert arg == mock_val + + +def test_create_session_flattened_error(): + client = ConversationalSearchServiceClient( + 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.create_session( + conversational_search_service.CreateSessionRequest(), + parent="parent_value", + session=gcd_session.Session(name="name_value"), + ) + + +@pytest.mark.asyncio +async def test_create_session_flattened_async(): + client = ConversationalSearchServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.create_session), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = gcd_session.Session() + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(gcd_session.Session()) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.create_session( + parent="parent_value", + session=gcd_session.Session(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].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].session + mock_val = gcd_session.Session(name="name_value") + assert arg == mock_val + + +@pytest.mark.asyncio +async def test_create_session_flattened_error_async(): + client = ConversationalSearchServiceAsyncClient( + 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.create_session( + conversational_search_service.CreateSessionRequest(), + parent="parent_value", + session=gcd_session.Session(name="name_value"), + ) + + +@pytest.mark.parametrize( + "request_type", + [ + conversational_search_service.DeleteSessionRequest, + dict, + ], +) +def test_delete_session(request_type, transport: str = "grpc"): + client = ConversationalSearchServiceClient( + 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.delete_session), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = None + response = client.delete_session(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = conversational_search_service.DeleteSessionRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert response is None + + +def test_delete_session_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 = ConversationalSearchServiceClient( + 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.delete_session), "__call__") as call: + client.delete_session() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == conversational_search_service.DeleteSessionRequest() + + +def test_delete_session_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 = ConversationalSearchServiceClient( + 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 = conversational_search_service.DeleteSessionRequest( + name="name_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.delete_session), "__call__") as call: + client.delete_session(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == conversational_search_service.DeleteSessionRequest( + name="name_value", + ) + + +@pytest.mark.asyncio +async def test_delete_session_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 = ConversationalSearchServiceAsyncClient( + 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.delete_session), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(None) + response = await client.delete_session() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == conversational_search_service.DeleteSessionRequest() + + +@pytest.mark.asyncio +async def test_delete_session_async( + transport: str = "grpc_asyncio", + request_type=conversational_search_service.DeleteSessionRequest, +): + client = ConversationalSearchServiceAsyncClient( + 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.delete_session), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(None) + response = await client.delete_session(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = conversational_search_service.DeleteSessionRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert response is None + + +@pytest.mark.asyncio +async def test_delete_session_async_from_dict(): + await test_delete_session_async(request_type=dict) + + +def test_delete_session_field_headers(): + client = ConversationalSearchServiceClient( + 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 = conversational_search_service.DeleteSessionRequest() + + request.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.delete_session), "__call__") as call: + call.return_value = None + client.delete_session(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_delete_session_field_headers_async(): + client = ConversationalSearchServiceAsyncClient( + 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 = conversational_search_service.DeleteSessionRequest() + + request.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.delete_session), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(None) + await client.delete_session(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_delete_session_flattened(): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.delete_session), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = None + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.delete_session( + 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_delete_session_flattened_error(): + client = ConversationalSearchServiceClient( + 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.delete_session( + conversational_search_service.DeleteSessionRequest(), + name="name_value", + ) + + +@pytest.mark.asyncio +async def test_delete_session_flattened_async(): + client = ConversationalSearchServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.delete_session), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = None + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(None) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.delete_session( + 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_delete_session_flattened_error_async(): + client = ConversationalSearchServiceAsyncClient( + 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.delete_session( + conversational_search_service.DeleteSessionRequest(), + name="name_value", + ) + + +@pytest.mark.parametrize( + "request_type", + [ + conversational_search_service.UpdateSessionRequest, + dict, + ], +) +def test_update_session(request_type, transport: str = "grpc"): + client = ConversationalSearchServiceClient( + 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_session), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = gcd_session.Session( + name="name_value", + state=gcd_session.Session.State.IN_PROGRESS, + user_pseudo_id="user_pseudo_id_value", + ) + response = client.update_session(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = conversational_search_service.UpdateSessionRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, gcd_session.Session) + assert response.name == "name_value" + assert response.state == gcd_session.Session.State.IN_PROGRESS + assert response.user_pseudo_id == "user_pseudo_id_value" + + +def test_update_session_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 = ConversationalSearchServiceClient( + 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_session), "__call__") as call: + client.update_session() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == conversational_search_service.UpdateSessionRequest() + + +def test_update_session_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 = ConversationalSearchServiceClient( + 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 = conversational_search_service.UpdateSessionRequest() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.update_session), "__call__") as call: + client.update_session(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == conversational_search_service.UpdateSessionRequest() + + +@pytest.mark.asyncio +async def test_update_session_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 = ConversationalSearchServiceAsyncClient( + 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_session), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + gcd_session.Session( + name="name_value", + state=gcd_session.Session.State.IN_PROGRESS, + user_pseudo_id="user_pseudo_id_value", + ) + ) + response = await client.update_session() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == conversational_search_service.UpdateSessionRequest() + + +@pytest.mark.asyncio +async def test_update_session_async( + transport: str = "grpc_asyncio", + request_type=conversational_search_service.UpdateSessionRequest, +): + client = ConversationalSearchServiceAsyncClient( + 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_session), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + gcd_session.Session( + name="name_value", + state=gcd_session.Session.State.IN_PROGRESS, + user_pseudo_id="user_pseudo_id_value", + ) + ) + response = await client.update_session(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = conversational_search_service.UpdateSessionRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, gcd_session.Session) + assert response.name == "name_value" + assert response.state == gcd_session.Session.State.IN_PROGRESS + assert response.user_pseudo_id == "user_pseudo_id_value" + + +@pytest.mark.asyncio +async def test_update_session_async_from_dict(): + await test_update_session_async(request_type=dict) + + +def test_update_session_field_headers(): + client = ConversationalSearchServiceClient( + 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 = conversational_search_service.UpdateSessionRequest() + + request.session.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.update_session), "__call__") as call: + call.return_value = gcd_session.Session() + client.update_session(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", + "session.name=name_value", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_update_session_field_headers_async(): + client = ConversationalSearchServiceAsyncClient( + 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 = conversational_search_service.UpdateSessionRequest() + + request.session.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.update_session), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(gcd_session.Session()) + await client.update_session(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", + "session.name=name_value", + ) in kw["metadata"] + + +def test_update_session_flattened(): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.update_session), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = gcd_session.Session() + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.update_session( + session=gcd_session.Session(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].session + mock_val = gcd_session.Session(name="name_value") + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val + + +def test_update_session_flattened_error(): + client = ConversationalSearchServiceClient( + 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_session( + conversational_search_service.UpdateSessionRequest(), + session=gcd_session.Session(name="name_value"), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + +@pytest.mark.asyncio +async def test_update_session_flattened_async(): + client = ConversationalSearchServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.update_session), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = gcd_session.Session() + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(gcd_session.Session()) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.update_session( + session=gcd_session.Session(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].session + mock_val = gcd_session.Session(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_session_flattened_error_async(): + client = ConversationalSearchServiceAsyncClient( + 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_session( + conversational_search_service.UpdateSessionRequest(), + session=gcd_session.Session(name="name_value"), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + +@pytest.mark.parametrize( + "request_type", + [ + conversational_search_service.GetSessionRequest, + dict, + ], +) +def test_get_session(request_type, transport: str = "grpc"): + client = ConversationalSearchServiceClient( + 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_session), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = session.Session( + name="name_value", + state=session.Session.State.IN_PROGRESS, + user_pseudo_id="user_pseudo_id_value", + ) + response = client.get_session(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = conversational_search_service.GetSessionRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, session.Session) + assert response.name == "name_value" + assert response.state == session.Session.State.IN_PROGRESS + assert response.user_pseudo_id == "user_pseudo_id_value" + + +def test_get_session_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 = ConversationalSearchServiceClient( + 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_session), "__call__") as call: + client.get_session() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == conversational_search_service.GetSessionRequest() + + +def test_get_session_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 = ConversationalSearchServiceClient( + 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 = conversational_search_service.GetSessionRequest( + name="name_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_session), "__call__") as call: + client.get_session(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == conversational_search_service.GetSessionRequest( + name="name_value", + ) + + +@pytest.mark.asyncio +async def test_get_session_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 = ConversationalSearchServiceAsyncClient( + 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_session), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + session.Session( + name="name_value", + state=session.Session.State.IN_PROGRESS, + user_pseudo_id="user_pseudo_id_value", + ) + ) + response = await client.get_session() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == conversational_search_service.GetSessionRequest() + + +@pytest.mark.asyncio +async def test_get_session_async( + transport: str = "grpc_asyncio", + request_type=conversational_search_service.GetSessionRequest, +): + client = ConversationalSearchServiceAsyncClient( + 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_session), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + session.Session( + name="name_value", + state=session.Session.State.IN_PROGRESS, + user_pseudo_id="user_pseudo_id_value", + ) + ) + response = await client.get_session(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = conversational_search_service.GetSessionRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, session.Session) + assert response.name == "name_value" + assert response.state == session.Session.State.IN_PROGRESS + assert response.user_pseudo_id == "user_pseudo_id_value" + + +@pytest.mark.asyncio +async def test_get_session_async_from_dict(): + await test_get_session_async(request_type=dict) + + +def test_get_session_field_headers(): + client = ConversationalSearchServiceClient( + 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 = conversational_search_service.GetSessionRequest() + + request.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_session), "__call__") as call: + call.return_value = session.Session() + client.get_session(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_session_field_headers_async(): + client = ConversationalSearchServiceAsyncClient( + 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 = conversational_search_service.GetSessionRequest() + + request.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_session), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(session.Session()) + await client.get_session(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_session_flattened(): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_session), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = session.Session() + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.get_session( + 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_session_flattened_error(): + client = ConversationalSearchServiceClient( + 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_session( + conversational_search_service.GetSessionRequest(), + name="name_value", + ) + + +@pytest.mark.asyncio +async def test_get_session_flattened_async(): + client = ConversationalSearchServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_session), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = session.Session() + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(session.Session()) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.get_session( + 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_session_flattened_error_async(): + client = ConversationalSearchServiceAsyncClient( + 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_session( + conversational_search_service.GetSessionRequest(), + name="name_value", + ) + + +@pytest.mark.parametrize( + "request_type", + [ + conversational_search_service.ListSessionsRequest, + dict, + ], +) +def test_list_sessions(request_type, transport: str = "grpc"): + client = ConversationalSearchServiceClient( + 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_sessions), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = conversational_search_service.ListSessionsResponse( + next_page_token="next_page_token_value", + ) + response = client.list_sessions(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = conversational_search_service.ListSessionsRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, pagers.ListSessionsPager) + assert response.next_page_token == "next_page_token_value" + + +def test_list_sessions_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 = ConversationalSearchServiceClient( + 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_sessions), "__call__") as call: + client.list_sessions() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == conversational_search_service.ListSessionsRequest() + + +def test_list_sessions_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 = ConversationalSearchServiceClient( + 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 = conversational_search_service.ListSessionsRequest( + parent="parent_value", + page_token="page_token_value", + filter="filter_value", + order_by="order_by_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_sessions), "__call__") as call: + client.list_sessions(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == conversational_search_service.ListSessionsRequest( + parent="parent_value", + page_token="page_token_value", + filter="filter_value", + order_by="order_by_value", + ) + + +@pytest.mark.asyncio +async def test_list_sessions_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 = ConversationalSearchServiceAsyncClient( + 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_sessions), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + conversational_search_service.ListSessionsResponse( + next_page_token="next_page_token_value", + ) + ) + response = await client.list_sessions() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == conversational_search_service.ListSessionsRequest() + + +@pytest.mark.asyncio +async def test_list_sessions_async( + transport: str = "grpc_asyncio", + request_type=conversational_search_service.ListSessionsRequest, +): + client = ConversationalSearchServiceAsyncClient( + 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_sessions), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + conversational_search_service.ListSessionsResponse( + next_page_token="next_page_token_value", + ) + ) + response = await client.list_sessions(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = conversational_search_service.ListSessionsRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, pagers.ListSessionsAsyncPager) + assert response.next_page_token == "next_page_token_value" + + +@pytest.mark.asyncio +async def test_list_sessions_async_from_dict(): + await test_list_sessions_async(request_type=dict) + + +def test_list_sessions_field_headers(): + client = ConversationalSearchServiceClient( + 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 = conversational_search_service.ListSessionsRequest() + + request.parent = "parent_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_sessions), "__call__") as call: + call.return_value = conversational_search_service.ListSessionsResponse() + client.list_sessions(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_sessions_field_headers_async(): + client = ConversationalSearchServiceAsyncClient( + 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 = conversational_search_service.ListSessionsRequest() + + request.parent = "parent_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_sessions), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + conversational_search_service.ListSessionsResponse() + ) + await client.list_sessions(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_sessions_flattened(): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_sessions), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = conversational_search_service.ListSessionsResponse() + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.list_sessions( + 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_sessions_flattened_error(): + client = ConversationalSearchServiceClient( + 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_sessions( + conversational_search_service.ListSessionsRequest(), + parent="parent_value", + ) + + +@pytest.mark.asyncio +async def test_list_sessions_flattened_async(): + client = ConversationalSearchServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_sessions), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = conversational_search_service.ListSessionsResponse() + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + conversational_search_service.ListSessionsResponse() + ) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.list_sessions( + 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_sessions_flattened_error_async(): + client = ConversationalSearchServiceAsyncClient( + 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_sessions( + conversational_search_service.ListSessionsRequest(), + parent="parent_value", + ) + + +def test_list_sessions_pager(transport_name: str = "grpc"): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport_name, + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_sessions), "__call__") as call: + # Set the response to a series of pages. + call.side_effect = ( + conversational_search_service.ListSessionsResponse( + sessions=[ + session.Session(), + session.Session(), + session.Session(), + ], + next_page_token="abc", + ), + conversational_search_service.ListSessionsResponse( + sessions=[], + next_page_token="def", + ), + conversational_search_service.ListSessionsResponse( + sessions=[ + session.Session(), + ], + next_page_token="ghi", + ), + conversational_search_service.ListSessionsResponse( + sessions=[ + session.Session(), + session.Session(), + ], + ), + RuntimeError, + ) + + metadata = () + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("parent", ""),)), + ) + pager = client.list_sessions(request={}) + + assert pager._metadata == metadata + + results = list(pager) + assert len(results) == 6 + assert all(isinstance(i, session.Session) for i in results) + + +def test_list_sessions_pages(transport_name: str = "grpc"): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport_name, + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_sessions), "__call__") as call: + # Set the response to a series of pages. + call.side_effect = ( + conversational_search_service.ListSessionsResponse( + sessions=[ + session.Session(), + session.Session(), + session.Session(), + ], + next_page_token="abc", + ), + conversational_search_service.ListSessionsResponse( + sessions=[], + next_page_token="def", + ), + conversational_search_service.ListSessionsResponse( + sessions=[ + session.Session(), + ], + next_page_token="ghi", + ), + conversational_search_service.ListSessionsResponse( + sessions=[ + session.Session(), + session.Session(), + ], + ), + RuntimeError, + ) + pages = list(client.list_sessions(request={}).pages) + for page_, token in zip(pages, ["abc", "def", "ghi", ""]): + assert page_.raw_page.next_page_token == token + + +@pytest.mark.asyncio +async def test_list_sessions_async_pager(): + client = ConversationalSearchServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_sessions), "__call__", new_callable=mock.AsyncMock + ) as call: + # Set the response to a series of pages. + call.side_effect = ( + conversational_search_service.ListSessionsResponse( + sessions=[ + session.Session(), + session.Session(), + session.Session(), + ], + next_page_token="abc", + ), + conversational_search_service.ListSessionsResponse( + sessions=[], + next_page_token="def", + ), + conversational_search_service.ListSessionsResponse( + sessions=[ + session.Session(), + ], + next_page_token="ghi", + ), + conversational_search_service.ListSessionsResponse( + sessions=[ + session.Session(), + session.Session(), + ], + ), + RuntimeError, + ) + async_pager = await client.list_sessions( + request={}, + ) + assert async_pager.next_page_token == "abc" + responses = [] + async for response in async_pager: # pragma: no branch + responses.append(response) + + assert len(responses) == 6 + assert all(isinstance(i, session.Session) for i in responses) + + +@pytest.mark.asyncio +async def test_list_sessions_async_pages(): + client = ConversationalSearchServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_sessions), "__call__", new_callable=mock.AsyncMock + ) as call: + # Set the response to a series of pages. + call.side_effect = ( + conversational_search_service.ListSessionsResponse( + sessions=[ + session.Session(), + session.Session(), + session.Session(), + ], + next_page_token="abc", + ), + conversational_search_service.ListSessionsResponse( + sessions=[], + next_page_token="def", + ), + conversational_search_service.ListSessionsResponse( + sessions=[ + session.Session(), + ], + next_page_token="ghi", + ), + conversational_search_service.ListSessionsResponse( + sessions=[ + session.Session(), + session.Session(), + ], + ), + RuntimeError, + ) + pages = [] + # Workaround issue in python 3.9 related to code coverage by adding `# pragma: no branch` + # See https://github.com/googleapis/gapic-generator-python/pull/1174#issuecomment-1025132372 + async for page_ in ( # pragma: no branch + await client.list_sessions(request={}) + ).pages: + pages.append(page_) + for page_, token in zip(pages, ["abc", "def", "ghi", ""]): + assert page_.raw_page.next_page_token == token + + @pytest.mark.parametrize( "request_type", [ @@ -3260,7 +5398,2038 @@ async def test_list_conversations_async_pages(): dict, ], ) -def test_converse_conversation_rest(request_type): +def test_converse_conversation_rest(request_type): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = { + "name": "projects/sample1/locations/sample2/dataStores/sample3/conversations/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 = conversational_search_service.ConverseConversationResponse( + related_questions=["related_questions_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 = conversational_search_service.ConverseConversationResponse.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.converse_conversation(request) + + # Establish that the response is the type that we expect. + assert isinstance( + response, conversational_search_service.ConverseConversationResponse + ) + assert response.related_questions == ["related_questions_value"] + + +def test_converse_conversation_rest_required_fields( + request_type=conversational_search_service.ConverseConversationRequest, +): + transport_class = transports.ConversationalSearchServiceRestTransport + + 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() + ).converse_conversation._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() + ).converse_conversation._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 = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = conversational_search_service.ConverseConversationResponse() + # 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 = ( + conversational_search_service.ConverseConversationResponse.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.converse_conversation(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_converse_conversation_rest_unset_required_fields(): + transport = transports.ConversationalSearchServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.converse_conversation._get_unset_required_fields({}) + assert set(unset_fields) == ( + set(()) + & set( + ( + "name", + "query", + ) + ) + ) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_converse_conversation_rest_interceptors(null_interceptor): + transport = transports.ConversationalSearchServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.ConversationalSearchServiceRestInterceptor(), + ) + client = ConversationalSearchServiceClient(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.ConversationalSearchServiceRestInterceptor, + "post_converse_conversation", + ) as post, mock.patch.object( + transports.ConversationalSearchServiceRestInterceptor, + "pre_converse_conversation", + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = conversational_search_service.ConverseConversationRequest.pb( + conversational_search_service.ConverseConversationRequest() + ) + 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 = ( + conversational_search_service.ConverseConversationResponse.to_json( + conversational_search_service.ConverseConversationResponse() + ) + ) + + request = conversational_search_service.ConverseConversationRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = conversational_search_service.ConverseConversationResponse() + + client.converse_conversation( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_converse_conversation_rest_bad_request( + transport: str = "rest", + request_type=conversational_search_service.ConverseConversationRequest, +): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = { + "name": "projects/sample1/locations/sample2/dataStores/sample3/conversations/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.converse_conversation(request) + + +def test_converse_conversation_rest_flattened(): + client = ConversationalSearchServiceClient( + 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 = conversational_search_service.ConverseConversationResponse() + + # get arguments that satisfy an http rule for this method + sample_request = { + "name": "projects/sample1/locations/sample2/dataStores/sample3/conversations/sample4" + } + + # get truthy value for each flattened field + mock_args = dict( + name="name_value", + query=conversation.TextInput(input="input_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 = conversational_search_service.ConverseConversationResponse.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.converse_conversation(**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/v1alpha/{name=projects/*/locations/*/dataStores/*/conversations/*}:converse" + % client.transport._host, + args[1], + ) + + +def test_converse_conversation_rest_flattened_error(transport: str = "rest"): + client = ConversationalSearchServiceClient( + 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.converse_conversation( + conversational_search_service.ConverseConversationRequest(), + name="name_value", + query=conversation.TextInput(input="input_value"), + ) + + +def test_converse_conversation_rest_error(): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + +@pytest.mark.parametrize( + "request_type", + [ + conversational_search_service.CreateConversationRequest, + dict, + ], +) +def test_create_conversation_rest(request_type): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = {"parent": "projects/sample1/locations/sample2/dataStores/sample3"} + request_init["conversation"] = { + "name": "name_value", + "state": 1, + "user_pseudo_id": "user_pseudo_id_value", + "messages": [ + { + "user_input": { + "input": "input_value", + "context": { + "context_documents": [ + "context_documents_value1", + "context_documents_value2", + ], + "active_document": "active_document_value", + }, + }, + "reply": { + "reply": "reply_value", + "references": [ + { + "uri": "uri_value", + "anchor_text": "anchor_text_value", + "start": 558, + "end": 311, + } + ], + "summary": { + "summary_text": "summary_text_value", + "summary_skipped_reasons": [1], + "safety_attributes": { + "categories": ["categories_value1", "categories_value2"], + "scores": [0.656, 0.657], + }, + "summary_with_metadata": { + "summary": "summary_value", + "citation_metadata": { + "citations": [ + { + "start_index": 1189, + "end_index": 942, + "sources": [{"reference_index": 1574}], + } + ] + }, + "references": [ + { + "title": "title_value", + "document": "document_value", + "uri": "uri_value", + "chunk_contents": [ + { + "content": "content_value", + "page_identifier": "page_identifier_value", + } + ], + } + ], + }, + }, + }, + "create_time": {"seconds": 751, "nanos": 543}, + } + ], + "start_time": {}, + "end_time": {}, + } + # 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 = conversational_search_service.CreateConversationRequest.meta.fields[ + "conversation" + ] + + 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["conversation"].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["conversation"][field])): + del request_init["conversation"][field][i][subfield] + else: + del request_init["conversation"][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 = gcd_conversation.Conversation( + name="name_value", + state=gcd_conversation.Conversation.State.IN_PROGRESS, + user_pseudo_id="user_pseudo_id_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 = gcd_conversation.Conversation.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.create_conversation(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, gcd_conversation.Conversation) + assert response.name == "name_value" + assert response.state == gcd_conversation.Conversation.State.IN_PROGRESS + assert response.user_pseudo_id == "user_pseudo_id_value" + + +def test_create_conversation_rest_required_fields( + request_type=conversational_search_service.CreateConversationRequest, +): + transport_class = transports.ConversationalSearchServiceRestTransport + + 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() + ).create_conversation._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() + ).create_conversation._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 = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = gcd_conversation.Conversation() + # 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 = gcd_conversation.Conversation.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.create_conversation(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_create_conversation_rest_unset_required_fields(): + transport = transports.ConversationalSearchServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.create_conversation._get_unset_required_fields({}) + assert set(unset_fields) == ( + set(()) + & set( + ( + "parent", + "conversation", + ) + ) + ) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_create_conversation_rest_interceptors(null_interceptor): + transport = transports.ConversationalSearchServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.ConversationalSearchServiceRestInterceptor(), + ) + client = ConversationalSearchServiceClient(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.ConversationalSearchServiceRestInterceptor, + "post_create_conversation", + ) as post, mock.patch.object( + transports.ConversationalSearchServiceRestInterceptor, "pre_create_conversation" + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = conversational_search_service.CreateConversationRequest.pb( + conversational_search_service.CreateConversationRequest() + ) + 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 = gcd_conversation.Conversation.to_json( + gcd_conversation.Conversation() + ) + + request = conversational_search_service.CreateConversationRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = gcd_conversation.Conversation() + + client.create_conversation( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_create_conversation_rest_bad_request( + transport: str = "rest", + request_type=conversational_search_service.CreateConversationRequest, +): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = {"parent": "projects/sample1/locations/sample2/dataStores/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.create_conversation(request) + + +def test_create_conversation_rest_flattened(): + client = ConversationalSearchServiceClient( + 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 = gcd_conversation.Conversation() + + # get arguments that satisfy an http rule for this method + sample_request = { + "parent": "projects/sample1/locations/sample2/dataStores/sample3" + } + + # get truthy value for each flattened field + mock_args = dict( + parent="parent_value", + conversation=gcd_conversation.Conversation(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 = gcd_conversation.Conversation.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.create_conversation(**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/v1alpha/{parent=projects/*/locations/*/dataStores/*}/conversations" + % client.transport._host, + args[1], + ) + + +def test_create_conversation_rest_flattened_error(transport: str = "rest"): + client = ConversationalSearchServiceClient( + 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.create_conversation( + conversational_search_service.CreateConversationRequest(), + parent="parent_value", + conversation=gcd_conversation.Conversation(name="name_value"), + ) + + +def test_create_conversation_rest_error(): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + +@pytest.mark.parametrize( + "request_type", + [ + conversational_search_service.DeleteConversationRequest, + dict, + ], +) +def test_delete_conversation_rest(request_type): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = { + "name": "projects/sample1/locations/sample2/dataStores/sample3/conversations/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 = None + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + json_return_value = "" + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + response = client.delete_conversation(request) + + # Establish that the response is the type that we expect. + assert response is None + + +def test_delete_conversation_rest_required_fields( + request_type=conversational_search_service.DeleteConversationRequest, +): + transport_class = transports.ConversationalSearchServiceRestTransport + + 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() + ).delete_conversation._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() + ).delete_conversation._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 = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = None + # 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": "delete", + "query_params": pb_request, + } + transcode.return_value = transcode_result + + response_value = Response() + response_value.status_code = 200 + json_return_value = "" + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + response = client.delete_conversation(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_delete_conversation_rest_unset_required_fields(): + transport = transports.ConversationalSearchServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.delete_conversation._get_unset_required_fields({}) + assert set(unset_fields) == (set(()) & set(("name",))) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_delete_conversation_rest_interceptors(null_interceptor): + transport = transports.ConversationalSearchServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.ConversationalSearchServiceRestInterceptor(), + ) + client = ConversationalSearchServiceClient(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.ConversationalSearchServiceRestInterceptor, "pre_delete_conversation" + ) as pre: + pre.assert_not_called() + pb_message = conversational_search_service.DeleteConversationRequest.pb( + conversational_search_service.DeleteConversationRequest() + ) + 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() + + request = conversational_search_service.DeleteConversationRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + + client.delete_conversation( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + + +def test_delete_conversation_rest_bad_request( + transport: str = "rest", + request_type=conversational_search_service.DeleteConversationRequest, +): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = { + "name": "projects/sample1/locations/sample2/dataStores/sample3/conversations/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.delete_conversation(request) + + +def test_delete_conversation_rest_flattened(): + client = ConversationalSearchServiceClient( + 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 = None + + # get arguments that satisfy an http rule for this method + sample_request = { + "name": "projects/sample1/locations/sample2/dataStores/sample3/conversations/sample4" + } + + # 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 + json_return_value = "" + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + client.delete_conversation(**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/v1alpha/{name=projects/*/locations/*/dataStores/*/conversations/*}" + % client.transport._host, + args[1], + ) + + +def test_delete_conversation_rest_flattened_error(transport: str = "rest"): + client = ConversationalSearchServiceClient( + 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.delete_conversation( + conversational_search_service.DeleteConversationRequest(), + name="name_value", + ) + + +def test_delete_conversation_rest_error(): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + +@pytest.mark.parametrize( + "request_type", + [ + conversational_search_service.UpdateConversationRequest, + dict, + ], +) +def test_update_conversation_rest(request_type): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = { + "conversation": { + "name": "projects/sample1/locations/sample2/dataStores/sample3/conversations/sample4" + } + } + request_init["conversation"] = { + "name": "projects/sample1/locations/sample2/dataStores/sample3/conversations/sample4", + "state": 1, + "user_pseudo_id": "user_pseudo_id_value", + "messages": [ + { + "user_input": { + "input": "input_value", + "context": { + "context_documents": [ + "context_documents_value1", + "context_documents_value2", + ], + "active_document": "active_document_value", + }, + }, + "reply": { + "reply": "reply_value", + "references": [ + { + "uri": "uri_value", + "anchor_text": "anchor_text_value", + "start": 558, + "end": 311, + } + ], + "summary": { + "summary_text": "summary_text_value", + "summary_skipped_reasons": [1], + "safety_attributes": { + "categories": ["categories_value1", "categories_value2"], + "scores": [0.656, 0.657], + }, + "summary_with_metadata": { + "summary": "summary_value", + "citation_metadata": { + "citations": [ + { + "start_index": 1189, + "end_index": 942, + "sources": [{"reference_index": 1574}], + } + ] + }, + "references": [ + { + "title": "title_value", + "document": "document_value", + "uri": "uri_value", + "chunk_contents": [ + { + "content": "content_value", + "page_identifier": "page_identifier_value", + } + ], + } + ], + }, + }, + }, + "create_time": {"seconds": 751, "nanos": 543}, + } + ], + "start_time": {}, + "end_time": {}, + } + # 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 = conversational_search_service.UpdateConversationRequest.meta.fields[ + "conversation" + ] + + 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["conversation"].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["conversation"][field])): + del request_init["conversation"][field][i][subfield] + else: + del request_init["conversation"][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 = gcd_conversation.Conversation( + name="name_value", + state=gcd_conversation.Conversation.State.IN_PROGRESS, + user_pseudo_id="user_pseudo_id_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 = gcd_conversation.Conversation.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_conversation(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, gcd_conversation.Conversation) + assert response.name == "name_value" + assert response.state == gcd_conversation.Conversation.State.IN_PROGRESS + assert response.user_pseudo_id == "user_pseudo_id_value" + + +def test_update_conversation_rest_required_fields( + request_type=conversational_search_service.UpdateConversationRequest, +): + transport_class = transports.ConversationalSearchServiceRestTransport + + 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_conversation._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_conversation._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 = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = gcd_conversation.Conversation() + # 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 = gcd_conversation.Conversation.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_conversation(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_update_conversation_rest_unset_required_fields(): + transport = transports.ConversationalSearchServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.update_conversation._get_unset_required_fields({}) + assert set(unset_fields) == (set(("updateMask",)) & set(("conversation",))) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_update_conversation_rest_interceptors(null_interceptor): + transport = transports.ConversationalSearchServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.ConversationalSearchServiceRestInterceptor(), + ) + client = ConversationalSearchServiceClient(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.ConversationalSearchServiceRestInterceptor, + "post_update_conversation", + ) as post, mock.patch.object( + transports.ConversationalSearchServiceRestInterceptor, "pre_update_conversation" + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = conversational_search_service.UpdateConversationRequest.pb( + conversational_search_service.UpdateConversationRequest() + ) + 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 = gcd_conversation.Conversation.to_json( + gcd_conversation.Conversation() + ) + + request = conversational_search_service.UpdateConversationRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = gcd_conversation.Conversation() + + client.update_conversation( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_update_conversation_rest_bad_request( + transport: str = "rest", + request_type=conversational_search_service.UpdateConversationRequest, +): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = { + "conversation": { + "name": "projects/sample1/locations/sample2/dataStores/sample3/conversations/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.update_conversation(request) + + +def test_update_conversation_rest_flattened(): + client = ConversationalSearchServiceClient( + 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 = gcd_conversation.Conversation() + + # get arguments that satisfy an http rule for this method + sample_request = { + "conversation": { + "name": "projects/sample1/locations/sample2/dataStores/sample3/conversations/sample4" + } + } + + # get truthy value for each flattened field + mock_args = dict( + conversation=gcd_conversation.Conversation(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 = gcd_conversation.Conversation.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_conversation(**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/v1alpha/{conversation.name=projects/*/locations/*/dataStores/*/conversations/*}" + % client.transport._host, + args[1], + ) + + +def test_update_conversation_rest_flattened_error(transport: str = "rest"): + client = ConversationalSearchServiceClient( + 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_conversation( + conversational_search_service.UpdateConversationRequest(), + conversation=gcd_conversation.Conversation(name="name_value"), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + +def test_update_conversation_rest_error(): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + +@pytest.mark.parametrize( + "request_type", + [ + conversational_search_service.GetConversationRequest, + dict, + ], +) +def test_get_conversation_rest(request_type): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = { + "name": "projects/sample1/locations/sample2/dataStores/sample3/conversations/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 = conversation.Conversation( + name="name_value", + state=conversation.Conversation.State.IN_PROGRESS, + user_pseudo_id="user_pseudo_id_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 = conversation.Conversation.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_conversation(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, conversation.Conversation) + assert response.name == "name_value" + assert response.state == conversation.Conversation.State.IN_PROGRESS + assert response.user_pseudo_id == "user_pseudo_id_value" + + +def test_get_conversation_rest_required_fields( + request_type=conversational_search_service.GetConversationRequest, +): + transport_class = transports.ConversationalSearchServiceRestTransport + + 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_conversation._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_conversation._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 = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = conversation.Conversation() + # 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 = conversation.Conversation.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_conversation(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_get_conversation_rest_unset_required_fields(): + transport = transports.ConversationalSearchServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.get_conversation._get_unset_required_fields({}) + assert set(unset_fields) == (set(()) & set(("name",))) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_get_conversation_rest_interceptors(null_interceptor): + transport = transports.ConversationalSearchServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.ConversationalSearchServiceRestInterceptor(), + ) + client = ConversationalSearchServiceClient(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.ConversationalSearchServiceRestInterceptor, "post_get_conversation" + ) as post, mock.patch.object( + transports.ConversationalSearchServiceRestInterceptor, "pre_get_conversation" + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = conversational_search_service.GetConversationRequest.pb( + conversational_search_service.GetConversationRequest() + ) + 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 = conversation.Conversation.to_json( + conversation.Conversation() + ) + + request = conversational_search_service.GetConversationRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = conversation.Conversation() + + client.get_conversation( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_get_conversation_rest_bad_request( + transport: str = "rest", + request_type=conversational_search_service.GetConversationRequest, +): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = { + "name": "projects/sample1/locations/sample2/dataStores/sample3/conversations/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.get_conversation(request) + + +def test_get_conversation_rest_flattened(): + client = ConversationalSearchServiceClient( + 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 = conversation.Conversation() + + # get arguments that satisfy an http rule for this method + sample_request = { + "name": "projects/sample1/locations/sample2/dataStores/sample3/conversations/sample4" + } + + # 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 = conversation.Conversation.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_conversation(**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/v1alpha/{name=projects/*/locations/*/dataStores/*/conversations/*}" + % client.transport._host, + args[1], + ) + + +def test_get_conversation_rest_flattened_error(transport: str = "rest"): + client = ConversationalSearchServiceClient( + 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_conversation( + conversational_search_service.GetConversationRequest(), + name="name_value", + ) + + +def test_get_conversation_rest_error(): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + +@pytest.mark.parametrize( + "request_type", + [ + conversational_search_service.ListConversationsRequest, + dict, + ], +) +def test_list_conversations_rest(request_type): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = {"parent": "projects/sample1/locations/sample2/dataStores/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 = conversational_search_service.ListConversationsResponse( + next_page_token="next_page_token_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 = conversational_search_service.ListConversationsResponse.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_conversations(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, pagers.ListConversationsPager) + assert response.next_page_token == "next_page_token_value" + + +def test_list_conversations_rest_required_fields( + request_type=conversational_search_service.ListConversationsRequest, +): + transport_class = transports.ConversationalSearchServiceRestTransport + + 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_conversations._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_conversations._get_unset_required_fields(jsonified_request) + # Check that path parameters and body parameters are not mixing in. + assert not set(unset_fields) - set( + ( + "filter", + "order_by", + "page_size", + "page_token", + ) + ) + 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 = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = conversational_search_service.ListConversationsResponse() + # 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 = conversational_search_service.ListConversationsResponse.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_conversations(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_list_conversations_rest_unset_required_fields(): + transport = transports.ConversationalSearchServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.list_conversations._get_unset_required_fields({}) + assert set(unset_fields) == ( + set( + ( + "filter", + "orderBy", + "pageSize", + "pageToken", + ) + ) + & set(("parent",)) + ) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_list_conversations_rest_interceptors(null_interceptor): + transport = transports.ConversationalSearchServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.ConversationalSearchServiceRestInterceptor(), + ) + client = ConversationalSearchServiceClient(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.ConversationalSearchServiceRestInterceptor, "post_list_conversations" + ) as post, mock.patch.object( + transports.ConversationalSearchServiceRestInterceptor, "pre_list_conversations" + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = conversational_search_service.ListConversationsRequest.pb( + conversational_search_service.ListConversationsRequest() + ) + 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 = ( + conversational_search_service.ListConversationsResponse.to_json( + conversational_search_service.ListConversationsResponse() + ) + ) + + request = conversational_search_service.ListConversationsRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = conversational_search_service.ListConversationsResponse() + + client.list_conversations( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_list_conversations_rest_bad_request( + transport: str = "rest", + request_type=conversational_search_service.ListConversationsRequest, +): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = {"parent": "projects/sample1/locations/sample2/dataStores/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_conversations(request) + + +def test_list_conversations_rest_flattened(): + client = ConversationalSearchServiceClient( + 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 = conversational_search_service.ListConversationsResponse() + + # get arguments that satisfy an http rule for this method + sample_request = { + "parent": "projects/sample1/locations/sample2/dataStores/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 = conversational_search_service.ListConversationsResponse.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_conversations(**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/v1alpha/{parent=projects/*/locations/*/dataStores/*}/conversations" + % client.transport._host, + args[1], + ) + + +def test_list_conversations_rest_flattened_error(transport: str = "rest"): + client = ConversationalSearchServiceClient( + 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_conversations( + conversational_search_service.ListConversationsRequest(), + parent="parent_value", + ) + + +def test_list_conversations_rest_pager(transport: str = "rest"): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # TODO(kbandes): remove this mock unless there's a good reason for it. + # with mock.patch.object(path_template, 'transcode') as transcode: + # Set the response as a series of pages + response = ( + conversational_search_service.ListConversationsResponse( + conversations=[ + conversation.Conversation(), + conversation.Conversation(), + conversation.Conversation(), + ], + next_page_token="abc", + ), + conversational_search_service.ListConversationsResponse( + conversations=[], + next_page_token="def", + ), + conversational_search_service.ListConversationsResponse( + conversations=[ + conversation.Conversation(), + ], + next_page_token="ghi", + ), + conversational_search_service.ListConversationsResponse( + conversations=[ + conversation.Conversation(), + conversation.Conversation(), + ], + ), + ) + # Two responses for two calls + response = response + response + + # Wrap the values into proper Response objs + response = tuple( + conversational_search_service.ListConversationsResponse.to_json(x) + for x in response + ) + return_values = tuple(Response() for i in response) + for return_val, response_val in zip(return_values, response): + return_val._content = response_val.encode("UTF-8") + return_val.status_code = 200 + req.side_effect = return_values + + sample_request = { + "parent": "projects/sample1/locations/sample2/dataStores/sample3" + } + + pager = client.list_conversations(request=sample_request) + + results = list(pager) + assert len(results) == 6 + assert all(isinstance(i, conversation.Conversation) for i in results) + + pages = list(client.list_conversations(request=sample_request).pages) + for page_, token in zip(pages, ["abc", "def", "ghi", ""]): + assert page_.raw_page.next_page_token == token + + +@pytest.mark.parametrize( + "request_type", + [ + conversational_search_service.AnswerQueryRequest, + dict, + ], +) +def test_answer_query_rest(request_type): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", @@ -3268,44 +7437,39 @@ def test_converse_conversation_rest(request_type): # send a request that will satisfy transcoding request_init = { - "name": "projects/sample1/locations/sample2/dataStores/sample3/conversations/sample4" + "serving_config": "projects/sample1/locations/sample2/dataStores/sample3/servingConfigs/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 = conversational_search_service.ConverseConversationResponse( - related_questions=["related_questions_value"], - ) + return_value = conversational_search_service.AnswerQueryResponse() # Wrap the value into a proper Response obj response_value = Response() response_value.status_code = 200 # Convert return value to protobuf type - return_value = conversational_search_service.ConverseConversationResponse.pb( + return_value = conversational_search_service.AnswerQueryResponse.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.converse_conversation(request) + response = client.answer_query(request) # Establish that the response is the type that we expect. - assert isinstance( - response, conversational_search_service.ConverseConversationResponse - ) - assert response.related_questions == ["related_questions_value"] + assert isinstance(response, conversational_search_service.AnswerQueryResponse) -def test_converse_conversation_rest_required_fields( - request_type=conversational_search_service.ConverseConversationRequest, +def test_answer_query_rest_required_fields( + request_type=conversational_search_service.AnswerQueryRequest, ): transport_class = transports.ConversationalSearchServiceRestTransport request_init = {} - request_init["name"] = "" + request_init["serving_config"] = "" request = request_type(**request_init) pb_request = request_type.pb(request) jsonified_request = json.loads( @@ -3316,21 +7480,21 @@ def test_converse_conversation_rest_required_fields( unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).converse_conversation._get_unset_required_fields(jsonified_request) + ).answer_query._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" + jsonified_request["servingConfig"] = "serving_config_value" unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).converse_conversation._get_unset_required_fields(jsonified_request) + ).answer_query._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" + assert "servingConfig" in jsonified_request + assert jsonified_request["servingConfig"] == "serving_config_value" client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), @@ -3339,7 +7503,7 @@ def test_converse_conversation_rest_required_fields( request = request_type(**request_init) # Designate an appropriate value for the returned response. - return_value = conversational_search_service.ConverseConversationResponse() + return_value = conversational_search_service.AnswerQueryResponse() # 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 @@ -3361,34 +7525,32 @@ def test_converse_conversation_rest_required_fields( response_value.status_code = 200 # Convert return value to protobuf type - return_value = ( - conversational_search_service.ConverseConversationResponse.pb( - return_value - ) + return_value = conversational_search_service.AnswerQueryResponse.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.converse_conversation(request) + response = client.answer_query(request) expected_params = [("$alt", "json;enum-encoding=int")] actual_params = req.call_args.kwargs["params"] assert expected_params == actual_params -def test_converse_conversation_rest_unset_required_fields(): +def test_answer_query_rest_unset_required_fields(): transport = transports.ConversationalSearchServiceRestTransport( credentials=ga_credentials.AnonymousCredentials ) - unset_fields = transport.converse_conversation._get_unset_required_fields({}) + unset_fields = transport.answer_query._get_unset_required_fields({}) assert set(unset_fields) == ( set(()) & set( ( - "name", + "servingConfig", "query", ) ) @@ -3396,7 +7558,7 @@ def test_converse_conversation_rest_unset_required_fields(): @pytest.mark.parametrize("null_interceptor", [True, False]) -def test_converse_conversation_rest_interceptors(null_interceptor): +def test_answer_query_rest_interceptors(null_interceptor): transport = transports.ConversationalSearchServiceRestTransport( credentials=ga_credentials.AnonymousCredentials(), interceptor=None @@ -3409,16 +7571,243 @@ def test_converse_conversation_rest_interceptors(null_interceptor): ) as req, mock.patch.object( path_template, "transcode" ) as transcode, mock.patch.object( - transports.ConversationalSearchServiceRestInterceptor, - "post_converse_conversation", + transports.ConversationalSearchServiceRestInterceptor, "post_answer_query" ) as post, mock.patch.object( - transports.ConversationalSearchServiceRestInterceptor, - "pre_converse_conversation", + transports.ConversationalSearchServiceRestInterceptor, "pre_answer_query" ) as pre: pre.assert_not_called() post.assert_not_called() - pb_message = conversational_search_service.ConverseConversationRequest.pb( - conversational_search_service.ConverseConversationRequest() + pb_message = conversational_search_service.AnswerQueryRequest.pb( + conversational_search_service.AnswerQueryRequest() + ) + 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 = ( + conversational_search_service.AnswerQueryResponse.to_json( + conversational_search_service.AnswerQueryResponse() + ) + ) + + request = conversational_search_service.AnswerQueryRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = conversational_search_service.AnswerQueryResponse() + + client.answer_query( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_answer_query_rest_bad_request( + transport: str = "rest", + request_type=conversational_search_service.AnswerQueryRequest, +): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = { + "serving_config": "projects/sample1/locations/sample2/dataStores/sample3/servingConfigs/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.answer_query(request) + + +def test_answer_query_rest_error(): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + +@pytest.mark.parametrize( + "request_type", + [ + conversational_search_service.GetAnswerRequest, + dict, + ], +) +def test_get_answer_rest(request_type): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = { + "name": "projects/sample1/locations/sample2/dataStores/sample3/sessions/sample4/answers/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 = answer.Answer( + name="name_value", + state=answer.Answer.State.IN_PROGRESS, + answer_text="answer_text_value", + related_questions=["related_questions_value"], + answer_skipped_reasons=[ + answer.Answer.AnswerSkippedReason.ADVERSARIAL_QUERY_IGNORED + ], + ) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = answer.Answer.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_answer(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, answer.Answer) + assert response.name == "name_value" + assert response.state == answer.Answer.State.IN_PROGRESS + assert response.answer_text == "answer_text_value" + assert response.related_questions == ["related_questions_value"] + assert response.answer_skipped_reasons == [ + answer.Answer.AnswerSkippedReason.ADVERSARIAL_QUERY_IGNORED + ] + + +def test_get_answer_rest_required_fields( + request_type=conversational_search_service.GetAnswerRequest, +): + transport_class = transports.ConversationalSearchServiceRestTransport + + 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_answer._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_answer._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 = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = answer.Answer() + # 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 = answer.Answer.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_answer(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_get_answer_rest_unset_required_fields(): + transport = transports.ConversationalSearchServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.get_answer._get_unset_required_fields({}) + assert set(unset_fields) == (set(()) & set(("name",))) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_get_answer_rest_interceptors(null_interceptor): + transport = transports.ConversationalSearchServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.ConversationalSearchServiceRestInterceptor(), + ) + client = ConversationalSearchServiceClient(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.ConversationalSearchServiceRestInterceptor, "post_get_answer" + ) as post, mock.patch.object( + transports.ConversationalSearchServiceRestInterceptor, "pre_get_answer" + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = conversational_search_service.GetAnswerRequest.pb( + conversational_search_service.GetAnswerRequest() ) transcode.return_value = { "method": "post", @@ -3430,21 +7819,17 @@ def test_converse_conversation_rest_interceptors(null_interceptor): req.return_value = Response() req.return_value.status_code = 200 req.return_value.request = PreparedRequest() - req.return_value._content = ( - conversational_search_service.ConverseConversationResponse.to_json( - conversational_search_service.ConverseConversationResponse() - ) - ) + req.return_value._content = answer.Answer.to_json(answer.Answer()) - request = conversational_search_service.ConverseConversationRequest() + request = conversational_search_service.GetAnswerRequest() metadata = [ ("key", "val"), ("cephalopod", "squid"), ] pre.return_value = request, metadata - post.return_value = conversational_search_service.ConverseConversationResponse() + post.return_value = answer.Answer() - client.converse_conversation( + client.get_answer( request, metadata=[ ("key", "val"), @@ -3456,9 +7841,8 @@ def test_converse_conversation_rest_interceptors(null_interceptor): post.assert_called_once() -def test_converse_conversation_rest_bad_request( - transport: str = "rest", - request_type=conversational_search_service.ConverseConversationRequest, +def test_get_answer_rest_bad_request( + transport: str = "rest", request_type=conversational_search_service.GetAnswerRequest ): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), @@ -3467,7 +7851,7 @@ def test_converse_conversation_rest_bad_request( # send a request that will satisfy transcoding request_init = { - "name": "projects/sample1/locations/sample2/dataStores/sample3/conversations/sample4" + "name": "projects/sample1/locations/sample2/dataStores/sample3/sessions/sample4/answers/sample5" } request = request_type(**request_init) @@ -3480,10 +7864,10 @@ def test_converse_conversation_rest_bad_request( response_value.status_code = 400 response_value.request = Request() req.return_value = response_value - client.converse_conversation(request) + client.get_answer(request) -def test_converse_conversation_rest_flattened(): +def test_get_answer_rest_flattened(): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", @@ -3492,17 +7876,16 @@ def test_converse_conversation_rest_flattened(): # 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 = conversational_search_service.ConverseConversationResponse() + return_value = answer.Answer() # get arguments that satisfy an http rule for this method sample_request = { - "name": "projects/sample1/locations/sample2/dataStores/sample3/conversations/sample4" + "name": "projects/sample1/locations/sample2/dataStores/sample3/sessions/sample4/answers/sample5" } # get truthy value for each flattened field mock_args = dict( name="name_value", - query=conversation.TextInput(input="input_value"), ) mock_args.update(sample_request) @@ -3510,27 +7893,25 @@ def test_converse_conversation_rest_flattened(): response_value = Response() response_value.status_code = 200 # Convert return value to protobuf type - return_value = conversational_search_service.ConverseConversationResponse.pb( - return_value - ) + return_value = answer.Answer.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.converse_conversation(**mock_args) + client.get_answer(**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/v1alpha/{name=projects/*/locations/*/dataStores/*/conversations/*}:converse" + "%s/v1alpha/{name=projects/*/locations/*/dataStores/*/sessions/*/answers/*}" % client.transport._host, args[1], ) -def test_converse_conversation_rest_flattened_error(transport: str = "rest"): +def test_get_answer_rest_flattened_error(transport: str = "rest"): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, @@ -3539,14 +7920,13 @@ def test_converse_conversation_rest_flattened_error(transport: str = "rest"): # Attempting to call a method with both a request object and flattened # fields is an error. with pytest.raises(ValueError): - client.converse_conversation( - conversational_search_service.ConverseConversationRequest(), + client.get_answer( + conversational_search_service.GetAnswerRequest(), name="name_value", - query=conversation.TextInput(input="input_value"), ) -def test_converse_conversation_rest_error(): +def test_get_answer_rest_error(): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest" ) @@ -3555,11 +7935,11 @@ def test_converse_conversation_rest_error(): @pytest.mark.parametrize( "request_type", [ - conversational_search_service.CreateConversationRequest, + conversational_search_service.CreateSessionRequest, dict, ], ) -def test_create_conversation_rest(request_type): +def test_create_session_rest(request_type): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", @@ -3567,64 +7947,17 @@ def test_create_conversation_rest(request_type): # send a request that will satisfy transcoding request_init = {"parent": "projects/sample1/locations/sample2/dataStores/sample3"} - request_init["conversation"] = { + request_init["session"] = { "name": "name_value", "state": 1, "user_pseudo_id": "user_pseudo_id_value", - "messages": [ + "turns": [ { - "user_input": { - "input": "input_value", - "context": { - "context_documents": [ - "context_documents_value1", - "context_documents_value2", - ], - "active_document": "active_document_value", - }, - }, - "reply": { - "reply": "reply_value", - "references": [ - { - "uri": "uri_value", - "anchor_text": "anchor_text_value", - "start": 558, - "end": 311, - } - ], - "summary": { - "summary_text": "summary_text_value", - "summary_skipped_reasons": [1], - "safety_attributes": { - "categories": ["categories_value1", "categories_value2"], - "scores": [0.656, 0.657], - }, - "summary_with_metadata": { - "summary": "summary_value", - "citation_metadata": { - "citations": [ - { - "start_index": 1189, - "end_index": 942, - "sources": [{"reference_index": 1574}], - } - ] - }, - "references": [ - { - "title": "title_value", - "document": "document_value", - "uri": "uri_value", - } - ], - }, - }, - }, - "create_time": {"seconds": 751, "nanos": 543}, + "query": {"text": "text_value", "query_id": "query_id_value"}, + "answer": "answer_value", } ], - "start_time": {}, + "start_time": {"seconds": 751, "nanos": 543}, "end_time": {}, } # The version of a generated dependency at test runtime may differ from the version used during generation. @@ -3632,8 +7965,8 @@ def test_create_conversation_rest(request_type): # See https://github.com/googleapis/gapic-generator-python/issues/1748 # Determine if the message type is proto-plus or protobuf - test_field = conversational_search_service.CreateConversationRequest.meta.fields[ - "conversation" + test_field = conversational_search_service.CreateSessionRequest.meta.fields[ + "session" ] def get_message_fields(field): @@ -3662,7 +7995,7 @@ def get_message_fields(field): # 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["conversation"].items(): # pragma: NO COVER + for field, value in request_init["session"].items(): # pragma: NO COVER result = None is_repeated = False # For repeated fields @@ -3692,18 +8025,18 @@ def get_message_fields(field): subfield = subfield_to_delete.get("subfield") if subfield: if field_repeated: - for i in range(0, len(request_init["conversation"][field])): - del request_init["conversation"][field][i][subfield] + for i in range(0, len(request_init["session"][field])): + del request_init["session"][field][i][subfield] else: - del request_init["conversation"][field][subfield] + del request_init["session"][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 = gcd_conversation.Conversation( + return_value = gcd_session.Session( name="name_value", - state=gcd_conversation.Conversation.State.IN_PROGRESS, + state=gcd_session.Session.State.IN_PROGRESS, user_pseudo_id="user_pseudo_id_value", ) @@ -3711,22 +8044,22 @@ def get_message_fields(field): response_value = Response() response_value.status_code = 200 # Convert return value to protobuf type - return_value = gcd_conversation.Conversation.pb(return_value) + return_value = gcd_session.Session.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.create_conversation(request) + response = client.create_session(request) # Establish that the response is the type that we expect. - assert isinstance(response, gcd_conversation.Conversation) + assert isinstance(response, gcd_session.Session) assert response.name == "name_value" - assert response.state == gcd_conversation.Conversation.State.IN_PROGRESS + assert response.state == gcd_session.Session.State.IN_PROGRESS assert response.user_pseudo_id == "user_pseudo_id_value" -def test_create_conversation_rest_required_fields( - request_type=conversational_search_service.CreateConversationRequest, +def test_create_session_rest_required_fields( + request_type=conversational_search_service.CreateSessionRequest, ): transport_class = transports.ConversationalSearchServiceRestTransport @@ -3742,7 +8075,7 @@ def test_create_conversation_rest_required_fields( unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).create_conversation._get_unset_required_fields(jsonified_request) + ).create_session._get_unset_required_fields(jsonified_request) jsonified_request.update(unset_fields) # verify required fields with default values are now present @@ -3751,7 +8084,7 @@ def test_create_conversation_rest_required_fields( unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).create_conversation._get_unset_required_fields(jsonified_request) + ).create_session._get_unset_required_fields(jsonified_request) jsonified_request.update(unset_fields) # verify required fields with non-default values are left alone @@ -3765,7 +8098,7 @@ def test_create_conversation_rest_required_fields( request = request_type(**request_init) # Designate an appropriate value for the returned response. - return_value = gcd_conversation.Conversation() + return_value = gcd_session.Session() # 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 @@ -3787,38 +8120,38 @@ def test_create_conversation_rest_required_fields( response_value.status_code = 200 # Convert return value to protobuf type - return_value = gcd_conversation.Conversation.pb(return_value) + return_value = gcd_session.Session.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.create_conversation(request) + response = client.create_session(request) expected_params = [("$alt", "json;enum-encoding=int")] actual_params = req.call_args.kwargs["params"] assert expected_params == actual_params -def test_create_conversation_rest_unset_required_fields(): +def test_create_session_rest_unset_required_fields(): transport = transports.ConversationalSearchServiceRestTransport( credentials=ga_credentials.AnonymousCredentials ) - unset_fields = transport.create_conversation._get_unset_required_fields({}) + unset_fields = transport.create_session._get_unset_required_fields({}) assert set(unset_fields) == ( set(()) & set( ( "parent", - "conversation", + "session", ) ) ) @pytest.mark.parametrize("null_interceptor", [True, False]) -def test_create_conversation_rest_interceptors(null_interceptor): +def test_create_session_rest_interceptors(null_interceptor): transport = transports.ConversationalSearchServiceRestTransport( credentials=ga_credentials.AnonymousCredentials(), interceptor=None @@ -3831,15 +8164,14 @@ def test_create_conversation_rest_interceptors(null_interceptor): ) as req, mock.patch.object( path_template, "transcode" ) as transcode, mock.patch.object( - transports.ConversationalSearchServiceRestInterceptor, - "post_create_conversation", + transports.ConversationalSearchServiceRestInterceptor, "post_create_session" ) as post, mock.patch.object( - transports.ConversationalSearchServiceRestInterceptor, "pre_create_conversation" + transports.ConversationalSearchServiceRestInterceptor, "pre_create_session" ) as pre: pre.assert_not_called() post.assert_not_called() - pb_message = conversational_search_service.CreateConversationRequest.pb( - conversational_search_service.CreateConversationRequest() + pb_message = conversational_search_service.CreateSessionRequest.pb( + conversational_search_service.CreateSessionRequest() ) transcode.return_value = { "method": "post", @@ -3851,19 +8183,17 @@ def test_create_conversation_rest_interceptors(null_interceptor): req.return_value = Response() req.return_value.status_code = 200 req.return_value.request = PreparedRequest() - req.return_value._content = gcd_conversation.Conversation.to_json( - gcd_conversation.Conversation() - ) + req.return_value._content = gcd_session.Session.to_json(gcd_session.Session()) - request = conversational_search_service.CreateConversationRequest() + request = conversational_search_service.CreateSessionRequest() metadata = [ ("key", "val"), ("cephalopod", "squid"), ] pre.return_value = request, metadata - post.return_value = gcd_conversation.Conversation() + post.return_value = gcd_session.Session() - client.create_conversation( + client.create_session( request, metadata=[ ("key", "val"), @@ -3875,9 +8205,9 @@ def test_create_conversation_rest_interceptors(null_interceptor): post.assert_called_once() -def test_create_conversation_rest_bad_request( +def test_create_session_rest_bad_request( transport: str = "rest", - request_type=conversational_search_service.CreateConversationRequest, + request_type=conversational_search_service.CreateSessionRequest, ): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), @@ -3897,10 +8227,10 @@ def test_create_conversation_rest_bad_request( response_value.status_code = 400 response_value.request = Request() req.return_value = response_value - client.create_conversation(request) + client.create_session(request) -def test_create_conversation_rest_flattened(): +def test_create_session_rest_flattened(): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", @@ -3909,7 +8239,7 @@ def test_create_conversation_rest_flattened(): # 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 = gcd_conversation.Conversation() + return_value = gcd_session.Session() # get arguments that satisfy an http rule for this method sample_request = { @@ -3919,7 +8249,7 @@ def test_create_conversation_rest_flattened(): # get truthy value for each flattened field mock_args = dict( parent="parent_value", - conversation=gcd_conversation.Conversation(name="name_value"), + session=gcd_session.Session(name="name_value"), ) mock_args.update(sample_request) @@ -3927,25 +8257,25 @@ def test_create_conversation_rest_flattened(): response_value = Response() response_value.status_code = 200 # Convert return value to protobuf type - return_value = gcd_conversation.Conversation.pb(return_value) + return_value = gcd_session.Session.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.create_conversation(**mock_args) + client.create_session(**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/v1alpha/{parent=projects/*/locations/*/dataStores/*}/conversations" + "%s/v1alpha/{parent=projects/*/locations/*/dataStores/*}/sessions" % client.transport._host, args[1], ) -def test_create_conversation_rest_flattened_error(transport: str = "rest"): +def test_create_session_rest_flattened_error(transport: str = "rest"): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, @@ -3954,14 +8284,14 @@ def test_create_conversation_rest_flattened_error(transport: str = "rest"): # Attempting to call a method with both a request object and flattened # fields is an error. with pytest.raises(ValueError): - client.create_conversation( - conversational_search_service.CreateConversationRequest(), + client.create_session( + conversational_search_service.CreateSessionRequest(), parent="parent_value", - conversation=gcd_conversation.Conversation(name="name_value"), + session=gcd_session.Session(name="name_value"), ) -def test_create_conversation_rest_error(): +def test_create_session_rest_error(): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest" ) @@ -3970,11 +8300,11 @@ def test_create_conversation_rest_error(): @pytest.mark.parametrize( "request_type", [ - conversational_search_service.DeleteConversationRequest, + conversational_search_service.DeleteSessionRequest, dict, ], ) -def test_delete_conversation_rest(request_type): +def test_delete_session_rest(request_type): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", @@ -3982,7 +8312,7 @@ def test_delete_conversation_rest(request_type): # send a request that will satisfy transcoding request_init = { - "name": "projects/sample1/locations/sample2/dataStores/sample3/conversations/sample4" + "name": "projects/sample1/locations/sample2/dataStores/sample3/sessions/sample4" } request = request_type(**request_init) @@ -3998,14 +8328,14 @@ def test_delete_conversation_rest(request_type): response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - response = client.delete_conversation(request) + response = client.delete_session(request) # Establish that the response is the type that we expect. assert response is None -def test_delete_conversation_rest_required_fields( - request_type=conversational_search_service.DeleteConversationRequest, +def test_delete_session_rest_required_fields( + request_type=conversational_search_service.DeleteSessionRequest, ): transport_class = transports.ConversationalSearchServiceRestTransport @@ -4021,7 +8351,7 @@ def test_delete_conversation_rest_required_fields( unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).delete_conversation._get_unset_required_fields(jsonified_request) + ).delete_session._get_unset_required_fields(jsonified_request) jsonified_request.update(unset_fields) # verify required fields with default values are now present @@ -4030,7 +8360,7 @@ def test_delete_conversation_rest_required_fields( unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).delete_conversation._get_unset_required_fields(jsonified_request) + ).delete_session._get_unset_required_fields(jsonified_request) jsonified_request.update(unset_fields) # verify required fields with non-default values are left alone @@ -4068,24 +8398,24 @@ def test_delete_conversation_rest_required_fields( response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - response = client.delete_conversation(request) + response = client.delete_session(request) expected_params = [("$alt", "json;enum-encoding=int")] actual_params = req.call_args.kwargs["params"] assert expected_params == actual_params -def test_delete_conversation_rest_unset_required_fields(): +def test_delete_session_rest_unset_required_fields(): transport = transports.ConversationalSearchServiceRestTransport( credentials=ga_credentials.AnonymousCredentials ) - unset_fields = transport.delete_conversation._get_unset_required_fields({}) + unset_fields = transport.delete_session._get_unset_required_fields({}) assert set(unset_fields) == (set(()) & set(("name",))) @pytest.mark.parametrize("null_interceptor", [True, False]) -def test_delete_conversation_rest_interceptors(null_interceptor): +def test_delete_session_rest_interceptors(null_interceptor): transport = transports.ConversationalSearchServiceRestTransport( credentials=ga_credentials.AnonymousCredentials(), interceptor=None @@ -4098,11 +8428,11 @@ def test_delete_conversation_rest_interceptors(null_interceptor): ) as req, mock.patch.object( path_template, "transcode" ) as transcode, mock.patch.object( - transports.ConversationalSearchServiceRestInterceptor, "pre_delete_conversation" + transports.ConversationalSearchServiceRestInterceptor, "pre_delete_session" ) as pre: pre.assert_not_called() - pb_message = conversational_search_service.DeleteConversationRequest.pb( - conversational_search_service.DeleteConversationRequest() + pb_message = conversational_search_service.DeleteSessionRequest.pb( + conversational_search_service.DeleteSessionRequest() ) transcode.return_value = { "method": "post", @@ -4115,14 +8445,14 @@ def test_delete_conversation_rest_interceptors(null_interceptor): req.return_value.status_code = 200 req.return_value.request = PreparedRequest() - request = conversational_search_service.DeleteConversationRequest() + request = conversational_search_service.DeleteSessionRequest() metadata = [ ("key", "val"), ("cephalopod", "squid"), ] pre.return_value = request, metadata - client.delete_conversation( + client.delete_session( request, metadata=[ ("key", "val"), @@ -4133,9 +8463,9 @@ def test_delete_conversation_rest_interceptors(null_interceptor): pre.assert_called_once() -def test_delete_conversation_rest_bad_request( +def test_delete_session_rest_bad_request( transport: str = "rest", - request_type=conversational_search_service.DeleteConversationRequest, + request_type=conversational_search_service.DeleteSessionRequest, ): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), @@ -4144,7 +8474,7 @@ def test_delete_conversation_rest_bad_request( # send a request that will satisfy transcoding request_init = { - "name": "projects/sample1/locations/sample2/dataStores/sample3/conversations/sample4" + "name": "projects/sample1/locations/sample2/dataStores/sample3/sessions/sample4" } request = request_type(**request_init) @@ -4157,10 +8487,10 @@ def test_delete_conversation_rest_bad_request( response_value.status_code = 400 response_value.request = Request() req.return_value = response_value - client.delete_conversation(request) + client.delete_session(request) -def test_delete_conversation_rest_flattened(): +def test_delete_session_rest_flattened(): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", @@ -4173,7 +8503,7 @@ def test_delete_conversation_rest_flattened(): # get arguments that satisfy an http rule for this method sample_request = { - "name": "projects/sample1/locations/sample2/dataStores/sample3/conversations/sample4" + "name": "projects/sample1/locations/sample2/dataStores/sample3/sessions/sample4" } # get truthy value for each flattened field @@ -4189,117 +8519,70 @@ def test_delete_conversation_rest_flattened(): response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - client.delete_conversation(**mock_args) + client.delete_session(**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/v1alpha/{name=projects/*/locations/*/dataStores/*/conversations/*}" - % client.transport._host, - args[1], - ) - - -def test_delete_conversation_rest_flattened_error(transport: str = "rest"): - client = ConversationalSearchServiceClient( - 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.delete_conversation( - conversational_search_service.DeleteConversationRequest(), - name="name_value", - ) - - -def test_delete_conversation_rest_error(): - client = ConversationalSearchServiceClient( - credentials=ga_credentials.AnonymousCredentials(), transport="rest" - ) - - -@pytest.mark.parametrize( - "request_type", - [ - conversational_search_service.UpdateConversationRequest, - dict, - ], -) -def test_update_conversation_rest(request_type): - client = ConversationalSearchServiceClient( - credentials=ga_credentials.AnonymousCredentials(), - transport="rest", - ) - - # send a request that will satisfy transcoding - request_init = { - "conversation": { - "name": "projects/sample1/locations/sample2/dataStores/sample3/conversations/sample4" - } - } - request_init["conversation"] = { - "name": "projects/sample1/locations/sample2/dataStores/sample3/conversations/sample4", - "state": 1, - "user_pseudo_id": "user_pseudo_id_value", - "messages": [ - { - "user_input": { - "input": "input_value", - "context": { - "context_documents": [ - "context_documents_value1", - "context_documents_value2", - ], - "active_document": "active_document_value", - }, - }, - "reply": { - "reply": "reply_value", - "references": [ - { - "uri": "uri_value", - "anchor_text": "anchor_text_value", - "start": 558, - "end": 311, - } - ], - "summary": { - "summary_text": "summary_text_value", - "summary_skipped_reasons": [1], - "safety_attributes": { - "categories": ["categories_value1", "categories_value2"], - "scores": [0.656, 0.657], - }, - "summary_with_metadata": { - "summary": "summary_value", - "citation_metadata": { - "citations": [ - { - "start_index": 1189, - "end_index": 942, - "sources": [{"reference_index": 1574}], - } - ] - }, - "references": [ - { - "title": "title_value", - "document": "document_value", - "uri": "uri_value", - } - ], - }, - }, - }, - "create_time": {"seconds": 751, "nanos": 543}, + _, args, _ = req.mock_calls[0] + assert path_template.validate( + "%s/v1alpha/{name=projects/*/locations/*/dataStores/*/sessions/*}" + % client.transport._host, + args[1], + ) + + +def test_delete_session_rest_flattened_error(transport: str = "rest"): + client = ConversationalSearchServiceClient( + 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.delete_session( + conversational_search_service.DeleteSessionRequest(), + name="name_value", + ) + + +def test_delete_session_rest_error(): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + +@pytest.mark.parametrize( + "request_type", + [ + conversational_search_service.UpdateSessionRequest, + dict, + ], +) +def test_update_session_rest(request_type): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = { + "session": { + "name": "projects/sample1/locations/sample2/dataStores/sample3/sessions/sample4" + } + } + request_init["session"] = { + "name": "projects/sample1/locations/sample2/dataStores/sample3/sessions/sample4", + "state": 1, + "user_pseudo_id": "user_pseudo_id_value", + "turns": [ + { + "query": {"text": "text_value", "query_id": "query_id_value"}, + "answer": "answer_value", } ], - "start_time": {}, + "start_time": {"seconds": 751, "nanos": 543}, "end_time": {}, } # The version of a generated dependency at test runtime may differ from the version used during generation. @@ -4307,8 +8590,8 @@ def test_update_conversation_rest(request_type): # See https://github.com/googleapis/gapic-generator-python/issues/1748 # Determine if the message type is proto-plus or protobuf - test_field = conversational_search_service.UpdateConversationRequest.meta.fields[ - "conversation" + test_field = conversational_search_service.UpdateSessionRequest.meta.fields[ + "session" ] def get_message_fields(field): @@ -4337,7 +8620,7 @@ def get_message_fields(field): # 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["conversation"].items(): # pragma: NO COVER + for field, value in request_init["session"].items(): # pragma: NO COVER result = None is_repeated = False # For repeated fields @@ -4367,18 +8650,18 @@ def get_message_fields(field): subfield = subfield_to_delete.get("subfield") if subfield: if field_repeated: - for i in range(0, len(request_init["conversation"][field])): - del request_init["conversation"][field][i][subfield] + for i in range(0, len(request_init["session"][field])): + del request_init["session"][field][i][subfield] else: - del request_init["conversation"][field][subfield] + del request_init["session"][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 = gcd_conversation.Conversation( + return_value = gcd_session.Session( name="name_value", - state=gcd_conversation.Conversation.State.IN_PROGRESS, + state=gcd_session.Session.State.IN_PROGRESS, user_pseudo_id="user_pseudo_id_value", ) @@ -4386,22 +8669,22 @@ def get_message_fields(field): response_value = Response() response_value.status_code = 200 # Convert return value to protobuf type - return_value = gcd_conversation.Conversation.pb(return_value) + return_value = gcd_session.Session.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_conversation(request) + response = client.update_session(request) # Establish that the response is the type that we expect. - assert isinstance(response, gcd_conversation.Conversation) + assert isinstance(response, gcd_session.Session) assert response.name == "name_value" - assert response.state == gcd_conversation.Conversation.State.IN_PROGRESS + assert response.state == gcd_session.Session.State.IN_PROGRESS assert response.user_pseudo_id == "user_pseudo_id_value" -def test_update_conversation_rest_required_fields( - request_type=conversational_search_service.UpdateConversationRequest, +def test_update_session_rest_required_fields( + request_type=conversational_search_service.UpdateSessionRequest, ): transport_class = transports.ConversationalSearchServiceRestTransport @@ -4416,14 +8699,14 @@ def test_update_conversation_rest_required_fields( unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).update_conversation._get_unset_required_fields(jsonified_request) + ).update_session._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_conversation._get_unset_required_fields(jsonified_request) + ).update_session._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) @@ -4437,7 +8720,7 @@ def test_update_conversation_rest_required_fields( request = request_type(**request_init) # Designate an appropriate value for the returned response. - return_value = gcd_conversation.Conversation() + return_value = gcd_session.Session() # 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 @@ -4459,30 +8742,30 @@ def test_update_conversation_rest_required_fields( response_value.status_code = 200 # Convert return value to protobuf type - return_value = gcd_conversation.Conversation.pb(return_value) + return_value = gcd_session.Session.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_conversation(request) + response = client.update_session(request) expected_params = [("$alt", "json;enum-encoding=int")] actual_params = req.call_args.kwargs["params"] assert expected_params == actual_params -def test_update_conversation_rest_unset_required_fields(): +def test_update_session_rest_unset_required_fields(): transport = transports.ConversationalSearchServiceRestTransport( credentials=ga_credentials.AnonymousCredentials ) - unset_fields = transport.update_conversation._get_unset_required_fields({}) - assert set(unset_fields) == (set(("updateMask",)) & set(("conversation",))) + unset_fields = transport.update_session._get_unset_required_fields({}) + assert set(unset_fields) == (set(("updateMask",)) & set(("session",))) @pytest.mark.parametrize("null_interceptor", [True, False]) -def test_update_conversation_rest_interceptors(null_interceptor): +def test_update_session_rest_interceptors(null_interceptor): transport = transports.ConversationalSearchServiceRestTransport( credentials=ga_credentials.AnonymousCredentials(), interceptor=None @@ -4495,15 +8778,14 @@ def test_update_conversation_rest_interceptors(null_interceptor): ) as req, mock.patch.object( path_template, "transcode" ) as transcode, mock.patch.object( - transports.ConversationalSearchServiceRestInterceptor, - "post_update_conversation", + transports.ConversationalSearchServiceRestInterceptor, "post_update_session" ) as post, mock.patch.object( - transports.ConversationalSearchServiceRestInterceptor, "pre_update_conversation" + transports.ConversationalSearchServiceRestInterceptor, "pre_update_session" ) as pre: pre.assert_not_called() post.assert_not_called() - pb_message = conversational_search_service.UpdateConversationRequest.pb( - conversational_search_service.UpdateConversationRequest() + pb_message = conversational_search_service.UpdateSessionRequest.pb( + conversational_search_service.UpdateSessionRequest() ) transcode.return_value = { "method": "post", @@ -4515,19 +8797,17 @@ def test_update_conversation_rest_interceptors(null_interceptor): req.return_value = Response() req.return_value.status_code = 200 req.return_value.request = PreparedRequest() - req.return_value._content = gcd_conversation.Conversation.to_json( - gcd_conversation.Conversation() - ) + req.return_value._content = gcd_session.Session.to_json(gcd_session.Session()) - request = conversational_search_service.UpdateConversationRequest() + request = conversational_search_service.UpdateSessionRequest() metadata = [ ("key", "val"), ("cephalopod", "squid"), ] pre.return_value = request, metadata - post.return_value = gcd_conversation.Conversation() + post.return_value = gcd_session.Session() - client.update_conversation( + client.update_session( request, metadata=[ ("key", "val"), @@ -4539,9 +8819,9 @@ def test_update_conversation_rest_interceptors(null_interceptor): post.assert_called_once() -def test_update_conversation_rest_bad_request( +def test_update_session_rest_bad_request( transport: str = "rest", - request_type=conversational_search_service.UpdateConversationRequest, + request_type=conversational_search_service.UpdateSessionRequest, ): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), @@ -4550,8 +8830,8 @@ def test_update_conversation_rest_bad_request( # send a request that will satisfy transcoding request_init = { - "conversation": { - "name": "projects/sample1/locations/sample2/dataStores/sample3/conversations/sample4" + "session": { + "name": "projects/sample1/locations/sample2/dataStores/sample3/sessions/sample4" } } request = request_type(**request_init) @@ -4565,10 +8845,10 @@ def test_update_conversation_rest_bad_request( response_value.status_code = 400 response_value.request = Request() req.return_value = response_value - client.update_conversation(request) + client.update_session(request) -def test_update_conversation_rest_flattened(): +def test_update_session_rest_flattened(): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", @@ -4577,18 +8857,18 @@ def test_update_conversation_rest_flattened(): # 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 = gcd_conversation.Conversation() + return_value = gcd_session.Session() # get arguments that satisfy an http rule for this method sample_request = { - "conversation": { - "name": "projects/sample1/locations/sample2/dataStores/sample3/conversations/sample4" + "session": { + "name": "projects/sample1/locations/sample2/dataStores/sample3/sessions/sample4" } } # get truthy value for each flattened field mock_args = dict( - conversation=gcd_conversation.Conversation(name="name_value"), + session=gcd_session.Session(name="name_value"), update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), ) mock_args.update(sample_request) @@ -4597,25 +8877,25 @@ def test_update_conversation_rest_flattened(): response_value = Response() response_value.status_code = 200 # Convert return value to protobuf type - return_value = gcd_conversation.Conversation.pb(return_value) + return_value = gcd_session.Session.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_conversation(**mock_args) + client.update_session(**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/v1alpha/{conversation.name=projects/*/locations/*/dataStores/*/conversations/*}" + "%s/v1alpha/{session.name=projects/*/locations/*/dataStores/*/sessions/*}" % client.transport._host, args[1], ) -def test_update_conversation_rest_flattened_error(transport: str = "rest"): +def test_update_session_rest_flattened_error(transport: str = "rest"): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, @@ -4624,14 +8904,14 @@ def test_update_conversation_rest_flattened_error(transport: str = "rest"): # Attempting to call a method with both a request object and flattened # fields is an error. with pytest.raises(ValueError): - client.update_conversation( - conversational_search_service.UpdateConversationRequest(), - conversation=gcd_conversation.Conversation(name="name_value"), + client.update_session( + conversational_search_service.UpdateSessionRequest(), + session=gcd_session.Session(name="name_value"), update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), ) -def test_update_conversation_rest_error(): +def test_update_session_rest_error(): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest" ) @@ -4640,11 +8920,11 @@ def test_update_conversation_rest_error(): @pytest.mark.parametrize( "request_type", [ - conversational_search_service.GetConversationRequest, + conversational_search_service.GetSessionRequest, dict, ], ) -def test_get_conversation_rest(request_type): +def test_get_session_rest(request_type): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", @@ -4652,16 +8932,16 @@ def test_get_conversation_rest(request_type): # send a request that will satisfy transcoding request_init = { - "name": "projects/sample1/locations/sample2/dataStores/sample3/conversations/sample4" + "name": "projects/sample1/locations/sample2/dataStores/sample3/sessions/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 = conversation.Conversation( + return_value = session.Session( name="name_value", - state=conversation.Conversation.State.IN_PROGRESS, + state=session.Session.State.IN_PROGRESS, user_pseudo_id="user_pseudo_id_value", ) @@ -4669,22 +8949,22 @@ def test_get_conversation_rest(request_type): response_value = Response() response_value.status_code = 200 # Convert return value to protobuf type - return_value = conversation.Conversation.pb(return_value) + return_value = session.Session.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_conversation(request) + response = client.get_session(request) # Establish that the response is the type that we expect. - assert isinstance(response, conversation.Conversation) + assert isinstance(response, session.Session) assert response.name == "name_value" - assert response.state == conversation.Conversation.State.IN_PROGRESS + assert response.state == session.Session.State.IN_PROGRESS assert response.user_pseudo_id == "user_pseudo_id_value" -def test_get_conversation_rest_required_fields( - request_type=conversational_search_service.GetConversationRequest, +def test_get_session_rest_required_fields( + request_type=conversational_search_service.GetSessionRequest, ): transport_class = transports.ConversationalSearchServiceRestTransport @@ -4700,7 +8980,7 @@ def test_get_conversation_rest_required_fields( unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).get_conversation._get_unset_required_fields(jsonified_request) + ).get_session._get_unset_required_fields(jsonified_request) jsonified_request.update(unset_fields) # verify required fields with default values are now present @@ -4709,7 +8989,7 @@ def test_get_conversation_rest_required_fields( unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).get_conversation._get_unset_required_fields(jsonified_request) + ).get_session._get_unset_required_fields(jsonified_request) jsonified_request.update(unset_fields) # verify required fields with non-default values are left alone @@ -4723,7 +9003,7 @@ def test_get_conversation_rest_required_fields( request = request_type(**request_init) # Designate an appropriate value for the returned response. - return_value = conversation.Conversation() + return_value = session.Session() # 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 @@ -4744,30 +9024,30 @@ def test_get_conversation_rest_required_fields( response_value.status_code = 200 # Convert return value to protobuf type - return_value = conversation.Conversation.pb(return_value) + return_value = session.Session.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_conversation(request) + response = client.get_session(request) expected_params = [("$alt", "json;enum-encoding=int")] actual_params = req.call_args.kwargs["params"] assert expected_params == actual_params -def test_get_conversation_rest_unset_required_fields(): +def test_get_session_rest_unset_required_fields(): transport = transports.ConversationalSearchServiceRestTransport( credentials=ga_credentials.AnonymousCredentials ) - unset_fields = transport.get_conversation._get_unset_required_fields({}) + unset_fields = transport.get_session._get_unset_required_fields({}) assert set(unset_fields) == (set(()) & set(("name",))) @pytest.mark.parametrize("null_interceptor", [True, False]) -def test_get_conversation_rest_interceptors(null_interceptor): +def test_get_session_rest_interceptors(null_interceptor): transport = transports.ConversationalSearchServiceRestTransport( credentials=ga_credentials.AnonymousCredentials(), interceptor=None @@ -4780,14 +9060,14 @@ def test_get_conversation_rest_interceptors(null_interceptor): ) as req, mock.patch.object( path_template, "transcode" ) as transcode, mock.patch.object( - transports.ConversationalSearchServiceRestInterceptor, "post_get_conversation" + transports.ConversationalSearchServiceRestInterceptor, "post_get_session" ) as post, mock.patch.object( - transports.ConversationalSearchServiceRestInterceptor, "pre_get_conversation" + transports.ConversationalSearchServiceRestInterceptor, "pre_get_session" ) as pre: pre.assert_not_called() post.assert_not_called() - pb_message = conversational_search_service.GetConversationRequest.pb( - conversational_search_service.GetConversationRequest() + pb_message = conversational_search_service.GetSessionRequest.pb( + conversational_search_service.GetSessionRequest() ) transcode.return_value = { "method": "post", @@ -4799,19 +9079,17 @@ def test_get_conversation_rest_interceptors(null_interceptor): req.return_value = Response() req.return_value.status_code = 200 req.return_value.request = PreparedRequest() - req.return_value._content = conversation.Conversation.to_json( - conversation.Conversation() - ) + req.return_value._content = session.Session.to_json(session.Session()) - request = conversational_search_service.GetConversationRequest() + request = conversational_search_service.GetSessionRequest() metadata = [ ("key", "val"), ("cephalopod", "squid"), ] pre.return_value = request, metadata - post.return_value = conversation.Conversation() + post.return_value = session.Session() - client.get_conversation( + client.get_session( request, metadata=[ ("key", "val"), @@ -4823,9 +9101,9 @@ def test_get_conversation_rest_interceptors(null_interceptor): post.assert_called_once() -def test_get_conversation_rest_bad_request( +def test_get_session_rest_bad_request( transport: str = "rest", - request_type=conversational_search_service.GetConversationRequest, + request_type=conversational_search_service.GetSessionRequest, ): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), @@ -4834,7 +9112,7 @@ def test_get_conversation_rest_bad_request( # send a request that will satisfy transcoding request_init = { - "name": "projects/sample1/locations/sample2/dataStores/sample3/conversations/sample4" + "name": "projects/sample1/locations/sample2/dataStores/sample3/sessions/sample4" } request = request_type(**request_init) @@ -4847,10 +9125,10 @@ def test_get_conversation_rest_bad_request( response_value.status_code = 400 response_value.request = Request() req.return_value = response_value - client.get_conversation(request) + client.get_session(request) -def test_get_conversation_rest_flattened(): +def test_get_session_rest_flattened(): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", @@ -4859,11 +9137,11 @@ def test_get_conversation_rest_flattened(): # 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 = conversation.Conversation() + return_value = session.Session() # get arguments that satisfy an http rule for this method sample_request = { - "name": "projects/sample1/locations/sample2/dataStores/sample3/conversations/sample4" + "name": "projects/sample1/locations/sample2/dataStores/sample3/sessions/sample4" } # get truthy value for each flattened field @@ -4876,25 +9154,25 @@ def test_get_conversation_rest_flattened(): response_value = Response() response_value.status_code = 200 # Convert return value to protobuf type - return_value = conversation.Conversation.pb(return_value) + return_value = session.Session.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_conversation(**mock_args) + client.get_session(**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/v1alpha/{name=projects/*/locations/*/dataStores/*/conversations/*}" + "%s/v1alpha/{name=projects/*/locations/*/dataStores/*/sessions/*}" % client.transport._host, args[1], ) -def test_get_conversation_rest_flattened_error(transport: str = "rest"): +def test_get_session_rest_flattened_error(transport: str = "rest"): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, @@ -4903,13 +9181,13 @@ def test_get_conversation_rest_flattened_error(transport: str = "rest"): # Attempting to call a method with both a request object and flattened # fields is an error. with pytest.raises(ValueError): - client.get_conversation( - conversational_search_service.GetConversationRequest(), + client.get_session( + conversational_search_service.GetSessionRequest(), name="name_value", ) -def test_get_conversation_rest_error(): +def test_get_session_rest_error(): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest" ) @@ -4918,11 +9196,11 @@ def test_get_conversation_rest_error(): @pytest.mark.parametrize( "request_type", [ - conversational_search_service.ListConversationsRequest, + conversational_search_service.ListSessionsRequest, dict, ], ) -def test_list_conversations_rest(request_type): +def test_list_sessions_rest(request_type): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", @@ -4935,7 +9213,7 @@ def test_list_conversations_rest(request_type): # 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 = conversational_search_service.ListConversationsResponse( + return_value = conversational_search_service.ListSessionsResponse( next_page_token="next_page_token_value", ) @@ -4943,22 +9221,22 @@ def test_list_conversations_rest(request_type): response_value = Response() response_value.status_code = 200 # Convert return value to protobuf type - return_value = conversational_search_service.ListConversationsResponse.pb( + return_value = conversational_search_service.ListSessionsResponse.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_conversations(request) + response = client.list_sessions(request) # Establish that the response is the type that we expect. - assert isinstance(response, pagers.ListConversationsPager) + assert isinstance(response, pagers.ListSessionsPager) assert response.next_page_token == "next_page_token_value" -def test_list_conversations_rest_required_fields( - request_type=conversational_search_service.ListConversationsRequest, +def test_list_sessions_rest_required_fields( + request_type=conversational_search_service.ListSessionsRequest, ): transport_class = transports.ConversationalSearchServiceRestTransport @@ -4974,7 +9252,7 @@ def test_list_conversations_rest_required_fields( unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).list_conversations._get_unset_required_fields(jsonified_request) + ).list_sessions._get_unset_required_fields(jsonified_request) jsonified_request.update(unset_fields) # verify required fields with default values are now present @@ -4983,7 +9261,7 @@ def test_list_conversations_rest_required_fields( unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).list_conversations._get_unset_required_fields(jsonified_request) + ).list_sessions._get_unset_required_fields(jsonified_request) # Check that path parameters and body parameters are not mixing in. assert not set(unset_fields) - set( ( @@ -5006,7 +9284,7 @@ def test_list_conversations_rest_required_fields( request = request_type(**request_init) # Designate an appropriate value for the returned response. - return_value = conversational_search_service.ListConversationsResponse() + return_value = conversational_search_service.ListSessionsResponse() # 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 @@ -5027,7 +9305,7 @@ def test_list_conversations_rest_required_fields( response_value.status_code = 200 # Convert return value to protobuf type - return_value = conversational_search_service.ListConversationsResponse.pb( + return_value = conversational_search_service.ListSessionsResponse.pb( return_value ) json_return_value = json_format.MessageToJson(return_value) @@ -5035,19 +9313,19 @@ def test_list_conversations_rest_required_fields( response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - response = client.list_conversations(request) + response = client.list_sessions(request) expected_params = [("$alt", "json;enum-encoding=int")] actual_params = req.call_args.kwargs["params"] assert expected_params == actual_params -def test_list_conversations_rest_unset_required_fields(): +def test_list_sessions_rest_unset_required_fields(): transport = transports.ConversationalSearchServiceRestTransport( credentials=ga_credentials.AnonymousCredentials ) - unset_fields = transport.list_conversations._get_unset_required_fields({}) + unset_fields = transport.list_sessions._get_unset_required_fields({}) assert set(unset_fields) == ( set( ( @@ -5062,7 +9340,7 @@ def test_list_conversations_rest_unset_required_fields(): @pytest.mark.parametrize("null_interceptor", [True, False]) -def test_list_conversations_rest_interceptors(null_interceptor): +def test_list_sessions_rest_interceptors(null_interceptor): transport = transports.ConversationalSearchServiceRestTransport( credentials=ga_credentials.AnonymousCredentials(), interceptor=None @@ -5075,14 +9353,14 @@ def test_list_conversations_rest_interceptors(null_interceptor): ) as req, mock.patch.object( path_template, "transcode" ) as transcode, mock.patch.object( - transports.ConversationalSearchServiceRestInterceptor, "post_list_conversations" + transports.ConversationalSearchServiceRestInterceptor, "post_list_sessions" ) as post, mock.patch.object( - transports.ConversationalSearchServiceRestInterceptor, "pre_list_conversations" + transports.ConversationalSearchServiceRestInterceptor, "pre_list_sessions" ) as pre: pre.assert_not_called() post.assert_not_called() - pb_message = conversational_search_service.ListConversationsRequest.pb( - conversational_search_service.ListConversationsRequest() + pb_message = conversational_search_service.ListSessionsRequest.pb( + conversational_search_service.ListSessionsRequest() ) transcode.return_value = { "method": "post", @@ -5095,20 +9373,20 @@ def test_list_conversations_rest_interceptors(null_interceptor): req.return_value.status_code = 200 req.return_value.request = PreparedRequest() req.return_value._content = ( - conversational_search_service.ListConversationsResponse.to_json( - conversational_search_service.ListConversationsResponse() + conversational_search_service.ListSessionsResponse.to_json( + conversational_search_service.ListSessionsResponse() ) ) - request = conversational_search_service.ListConversationsRequest() + request = conversational_search_service.ListSessionsRequest() metadata = [ ("key", "val"), ("cephalopod", "squid"), ] pre.return_value = request, metadata - post.return_value = conversational_search_service.ListConversationsResponse() + post.return_value = conversational_search_service.ListSessionsResponse() - client.list_conversations( + client.list_sessions( request, metadata=[ ("key", "val"), @@ -5120,9 +9398,9 @@ def test_list_conversations_rest_interceptors(null_interceptor): post.assert_called_once() -def test_list_conversations_rest_bad_request( +def test_list_sessions_rest_bad_request( transport: str = "rest", - request_type=conversational_search_service.ListConversationsRequest, + request_type=conversational_search_service.ListSessionsRequest, ): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), @@ -5142,10 +9420,10 @@ def test_list_conversations_rest_bad_request( response_value.status_code = 400 response_value.request = Request() req.return_value = response_value - client.list_conversations(request) + client.list_sessions(request) -def test_list_conversations_rest_flattened(): +def test_list_sessions_rest_flattened(): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", @@ -5154,7 +9432,7 @@ def test_list_conversations_rest_flattened(): # 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 = conversational_search_service.ListConversationsResponse() + return_value = conversational_search_service.ListSessionsResponse() # get arguments that satisfy an http rule for this method sample_request = { @@ -5171,27 +9449,27 @@ def test_list_conversations_rest_flattened(): response_value = Response() response_value.status_code = 200 # Convert return value to protobuf type - return_value = conversational_search_service.ListConversationsResponse.pb( + return_value = conversational_search_service.ListSessionsResponse.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_conversations(**mock_args) + client.list_sessions(**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/v1alpha/{parent=projects/*/locations/*/dataStores/*}/conversations" + "%s/v1alpha/{parent=projects/*/locations/*/dataStores/*}/sessions" % client.transport._host, args[1], ) -def test_list_conversations_rest_flattened_error(transport: str = "rest"): +def test_list_sessions_rest_flattened_error(transport: str = "rest"): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, @@ -5200,13 +9478,13 @@ def test_list_conversations_rest_flattened_error(transport: str = "rest"): # Attempting to call a method with both a request object and flattened # fields is an error. with pytest.raises(ValueError): - client.list_conversations( - conversational_search_service.ListConversationsRequest(), + client.list_sessions( + conversational_search_service.ListSessionsRequest(), parent="parent_value", ) -def test_list_conversations_rest_pager(transport: str = "rest"): +def test_list_sessions_rest_pager(transport: str = "rest"): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, @@ -5218,28 +9496,28 @@ def test_list_conversations_rest_pager(transport: str = "rest"): # with mock.patch.object(path_template, 'transcode') as transcode: # Set the response as a series of pages response = ( - conversational_search_service.ListConversationsResponse( - conversations=[ - conversation.Conversation(), - conversation.Conversation(), - conversation.Conversation(), + conversational_search_service.ListSessionsResponse( + sessions=[ + session.Session(), + session.Session(), + session.Session(), ], next_page_token="abc", ), - conversational_search_service.ListConversationsResponse( - conversations=[], + conversational_search_service.ListSessionsResponse( + sessions=[], next_page_token="def", ), - conversational_search_service.ListConversationsResponse( - conversations=[ - conversation.Conversation(), + conversational_search_service.ListSessionsResponse( + sessions=[ + session.Session(), ], next_page_token="ghi", ), - conversational_search_service.ListConversationsResponse( - conversations=[ - conversation.Conversation(), - conversation.Conversation(), + conversational_search_service.ListSessionsResponse( + sessions=[ + session.Session(), + session.Session(), ], ), ) @@ -5248,7 +9526,7 @@ def test_list_conversations_rest_pager(transport: str = "rest"): # Wrap the values into proper Response objs response = tuple( - conversational_search_service.ListConversationsResponse.to_json(x) + conversational_search_service.ListSessionsResponse.to_json(x) for x in response ) return_values = tuple(Response() for i in response) @@ -5261,13 +9539,13 @@ def test_list_conversations_rest_pager(transport: str = "rest"): "parent": "projects/sample1/locations/sample2/dataStores/sample3" } - pager = client.list_conversations(request=sample_request) + pager = client.list_sessions(request=sample_request) results = list(pager) assert len(results) == 6 - assert all(isinstance(i, conversation.Conversation) for i in results) + assert all(isinstance(i, session.Session) for i in results) - pages = list(client.list_conversations(request=sample_request).pages) + pages = list(client.list_sessions(request=sample_request).pages) for page_, token in zip(pages, ["abc", "def", "ghi", ""]): assert page_.raw_page.next_page_token == token @@ -5417,6 +9695,13 @@ def test_conversational_search_service_base_transport(): "update_conversation", "get_conversation", "list_conversations", + "answer_query", + "get_answer", + "create_session", + "delete_session", + "update_session", + "get_session", + "list_sessions", "get_operation", "list_operations", ) @@ -5704,6 +9989,27 @@ def test_conversational_search_service_client_transport_session_collision( session1 = client1.transport.list_conversations._session session2 = client2.transport.list_conversations._session assert session1 != session2 + session1 = client1.transport.answer_query._session + session2 = client2.transport.answer_query._session + assert session1 != session2 + session1 = client1.transport.get_answer._session + session2 = client2.transport.get_answer._session + assert session1 != session2 + session1 = client1.transport.create_session._session + session2 = client2.transport.create_session._session + assert session1 != session2 + session1 = client1.transport.delete_session._session + session2 = client2.transport.delete_session._session + assert session1 != session2 + session1 = client1.transport.update_session._session + session2 = client2.transport.update_session._session + assert session1 != session2 + session1 = client1.transport.get_session._session + session2 = client2.transport.get_session._session + assert session1 != session2 + session1 = client1.transport.list_sessions._session + session2 = client2.transport.list_sessions._session + assert session1 != session2 def test_conversational_search_service_grpc_transport_channel(): @@ -5832,13 +10138,47 @@ def test_conversational_search_service_transport_channel_mtls_with_adc(transport assert transport.grpc_channel == mock_grpc_channel -def test_chunk_path(): +def test_answer_path(): project = "squid" location = "clam" data_store = "whelk" - branch = "octopus" - document = "oyster" - chunk = "nudibranch" + session = "octopus" + answer = "oyster" + expected = "projects/{project}/locations/{location}/dataStores/{data_store}/sessions/{session}/answers/{answer}".format( + project=project, + location=location, + data_store=data_store, + session=session, + answer=answer, + ) + actual = ConversationalSearchServiceClient.answer_path( + project, location, data_store, session, answer + ) + assert expected == actual + + +def test_parse_answer_path(): + expected = { + "project": "nudibranch", + "location": "cuttlefish", + "data_store": "mussel", + "session": "winkle", + "answer": "nautilus", + } + path = ConversationalSearchServiceClient.answer_path(**expected) + + # Check that the path construction is reversible. + actual = ConversationalSearchServiceClient.parse_answer_path(path) + assert expected == actual + + +def test_chunk_path(): + project = "scallop" + location = "abalone" + data_store = "squid" + branch = "clam" + document = "whelk" + chunk = "octopus" expected = "projects/{project}/locations/{location}/dataStores/{data_store}/branches/{branch}/documents/{document}/chunks/{chunk}".format( project=project, location=location, @@ -5855,12 +10195,12 @@ def test_chunk_path(): def test_parse_chunk_path(): expected = { - "project": "cuttlefish", - "location": "mussel", - "data_store": "winkle", - "branch": "nautilus", - "document": "scallop", - "chunk": "abalone", + "project": "oyster", + "location": "nudibranch", + "data_store": "cuttlefish", + "branch": "mussel", + "document": "winkle", + "chunk": "nautilus", } path = ConversationalSearchServiceClient.chunk_path(**expected) @@ -5870,10 +10210,10 @@ def test_parse_chunk_path(): def test_conversation_path(): - project = "squid" - location = "clam" - data_store = "whelk" - conversation = "octopus" + project = "scallop" + location = "abalone" + data_store = "squid" + conversation = "clam" expected = "projects/{project}/locations/{location}/dataStores/{data_store}/conversations/{conversation}".format( project=project, location=location, @@ -5888,10 +10228,10 @@ def test_conversation_path(): def test_parse_conversation_path(): expected = { - "project": "oyster", - "location": "nudibranch", - "data_store": "cuttlefish", - "conversation": "mussel", + "project": "whelk", + "location": "octopus", + "data_store": "oyster", + "conversation": "nudibranch", } path = ConversationalSearchServiceClient.conversation_path(**expected) @@ -5901,9 +10241,9 @@ def test_parse_conversation_path(): def test_data_store_path(): - project = "winkle" - location = "nautilus" - data_store = "scallop" + project = "cuttlefish" + location = "mussel" + data_store = "winkle" expected = "projects/{project}/locations/{location}/dataStores/{data_store}".format( project=project, location=location, @@ -5917,9 +10257,9 @@ def test_data_store_path(): def test_parse_data_store_path(): expected = { - "project": "abalone", - "location": "squid", - "data_store": "clam", + "project": "nautilus", + "location": "scallop", + "data_store": "abalone", } path = ConversationalSearchServiceClient.data_store_path(**expected) @@ -5929,11 +10269,11 @@ def test_parse_data_store_path(): def test_document_path(): - project = "whelk" - location = "octopus" - data_store = "oyster" - branch = "nudibranch" - document = "cuttlefish" + project = "squid" + location = "clam" + data_store = "whelk" + branch = "octopus" + document = "oyster" expected = "projects/{project}/locations/{location}/dataStores/{data_store}/branches/{branch}/documents/{document}".format( project=project, location=location, @@ -5949,11 +10289,11 @@ def test_document_path(): def test_parse_document_path(): expected = { - "project": "mussel", - "location": "winkle", - "data_store": "nautilus", - "branch": "scallop", - "document": "abalone", + "project": "nudibranch", + "location": "cuttlefish", + "data_store": "mussel", + "branch": "winkle", + "document": "nautilus", } path = ConversationalSearchServiceClient.document_path(**expected) @@ -5963,10 +10303,10 @@ def test_parse_document_path(): def test_serving_config_path(): - project = "squid" - location = "clam" - data_store = "whelk" - serving_config = "octopus" + project = "scallop" + location = "abalone" + data_store = "squid" + serving_config = "clam" expected = "projects/{project}/locations/{location}/dataStores/{data_store}/servingConfigs/{serving_config}".format( project=project, location=location, @@ -5981,10 +10321,10 @@ def test_serving_config_path(): def test_parse_serving_config_path(): expected = { - "project": "oyster", - "location": "nudibranch", - "data_store": "cuttlefish", - "serving_config": "mussel", + "project": "whelk", + "location": "octopus", + "data_store": "oyster", + "serving_config": "nudibranch", } path = ConversationalSearchServiceClient.serving_config_path(**expected) @@ -5993,8 +10333,39 @@ def test_parse_serving_config_path(): assert expected == actual +def test_session_path(): + project = "cuttlefish" + location = "mussel" + data_store = "winkle" + session = "nautilus" + expected = "projects/{project}/locations/{location}/dataStores/{data_store}/sessions/{session}".format( + project=project, + location=location, + data_store=data_store, + session=session, + ) + actual = ConversationalSearchServiceClient.session_path( + project, location, data_store, session + ) + assert expected == actual + + +def test_parse_session_path(): + expected = { + "project": "scallop", + "location": "abalone", + "data_store": "squid", + "session": "clam", + } + path = ConversationalSearchServiceClient.session_path(**expected) + + # Check that the path construction is reversible. + actual = ConversationalSearchServiceClient.parse_session_path(path) + assert expected == actual + + def test_common_billing_account_path(): - billing_account = "winkle" + billing_account = "whelk" expected = "billingAccounts/{billing_account}".format( billing_account=billing_account, ) @@ -6006,7 +10377,7 @@ def test_common_billing_account_path(): def test_parse_common_billing_account_path(): expected = { - "billing_account": "nautilus", + "billing_account": "octopus", } path = ConversationalSearchServiceClient.common_billing_account_path(**expected) @@ -6016,7 +10387,7 @@ def test_parse_common_billing_account_path(): def test_common_folder_path(): - folder = "scallop" + folder = "oyster" expected = "folders/{folder}".format( folder=folder, ) @@ -6026,7 +10397,7 @@ def test_common_folder_path(): def test_parse_common_folder_path(): expected = { - "folder": "abalone", + "folder": "nudibranch", } path = ConversationalSearchServiceClient.common_folder_path(**expected) @@ -6036,7 +10407,7 @@ def test_parse_common_folder_path(): def test_common_organization_path(): - organization = "squid" + organization = "cuttlefish" expected = "organizations/{organization}".format( organization=organization, ) @@ -6046,7 +10417,7 @@ def test_common_organization_path(): def test_parse_common_organization_path(): expected = { - "organization": "clam", + "organization": "mussel", } path = ConversationalSearchServiceClient.common_organization_path(**expected) @@ -6056,7 +10427,7 @@ def test_parse_common_organization_path(): def test_common_project_path(): - project = "whelk" + project = "winkle" expected = "projects/{project}".format( project=project, ) @@ -6066,7 +10437,7 @@ def test_common_project_path(): def test_parse_common_project_path(): expected = { - "project": "octopus", + "project": "nautilus", } path = ConversationalSearchServiceClient.common_project_path(**expected) @@ -6076,8 +10447,8 @@ def test_parse_common_project_path(): def test_common_location_path(): - project = "oyster" - location = "nudibranch" + project = "scallop" + location = "abalone" expected = "projects/{project}/locations/{location}".format( project=project, location=location, @@ -6088,8 +10459,8 @@ def test_common_location_path(): def test_parse_common_location_path(): expected = { - "project": "cuttlefish", - "location": "mussel", + "project": "squid", + "location": "clam", } path = ConversationalSearchServiceClient.common_location_path(**expected) diff --git a/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1alpha/test_data_store_service.py b/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1alpha/test_data_store_service.py index ca977ef3b3a0..d53898e22dc0 100644 --- a/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1alpha/test_data_store_service.py +++ b/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1alpha/test_data_store_service.py @@ -3587,6 +3587,7 @@ def test_create_data_store_rest(request_type): "completable_option": 1, "recs_filterable_option": 1, "key_property_type": "key_property_type_value", + "advanced_site_search_data_sources": [1], } ], }, @@ -4888,6 +4889,7 @@ def test_update_data_store_rest(request_type): "completable_option": 1, "recs_filterable_option": 1, "key_property_type": "key_property_type_value", + "advanced_site_search_data_sources": [1], } ], }, diff --git a/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1alpha/test_document_service.py b/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1alpha/test_document_service.py index 47206f0e969f..13565fe5a3cc 100644 --- a/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1alpha/test_document_service.py +++ b/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1alpha/test_document_service.py @@ -3304,6 +3304,308 @@ async def test_purge_documents_field_headers_async(): ) in kw["metadata"] +@pytest.mark.parametrize( + "request_type", + [ + document_service.GetProcessedDocumentRequest, + dict, + ], +) +def test_get_processed_document(request_type, transport: str = "grpc"): + client = DocumentServiceClient( + 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_processed_document), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = document.ProcessedDocument( + document="document_value", + json_data="json_data_value", + ) + response = client.get_processed_document(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = document_service.GetProcessedDocumentRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, document.ProcessedDocument) + assert response.document == "document_value" + + +def test_get_processed_document_empty_call(): + # This test is a coverage failsafe to make sure that totally empty calls, + # i.e. request == None and no flattened fields passed, work. + client = DocumentServiceClient( + 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_processed_document), "__call__" + ) as call: + client.get_processed_document() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == document_service.GetProcessedDocumentRequest() + + +def test_get_processed_document_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 = DocumentServiceClient( + 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 = document_service.GetProcessedDocumentRequest( + name="name_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.get_processed_document), "__call__" + ) as call: + client.get_processed_document(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == document_service.GetProcessedDocumentRequest( + name="name_value", + ) + + +@pytest.mark.asyncio +async def test_get_processed_document_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 = DocumentServiceAsyncClient( + 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_processed_document), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + document.ProcessedDocument( + document="document_value", + ) + ) + response = await client.get_processed_document() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == document_service.GetProcessedDocumentRequest() + + +@pytest.mark.asyncio +async def test_get_processed_document_async( + transport: str = "grpc_asyncio", + request_type=document_service.GetProcessedDocumentRequest, +): + client = DocumentServiceAsyncClient( + 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_processed_document), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + document.ProcessedDocument( + document="document_value", + ) + ) + response = await client.get_processed_document(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = document_service.GetProcessedDocumentRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, document.ProcessedDocument) + assert response.document == "document_value" + + +@pytest.mark.asyncio +async def test_get_processed_document_async_from_dict(): + await test_get_processed_document_async(request_type=dict) + + +def test_get_processed_document_field_headers(): + client = DocumentServiceClient( + 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 = document_service.GetProcessedDocumentRequest() + + request.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.get_processed_document), "__call__" + ) as call: + call.return_value = document.ProcessedDocument() + client.get_processed_document(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "name=name_value", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_get_processed_document_field_headers_async(): + client = DocumentServiceAsyncClient( + 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 = document_service.GetProcessedDocumentRequest() + + request.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.get_processed_document), "__call__" + ) as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + document.ProcessedDocument() + ) + await client.get_processed_document(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "name=name_value", + ) in kw["metadata"] + + +def test_get_processed_document_flattened(): + client = DocumentServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.get_processed_document), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = document.ProcessedDocument() + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.get_processed_document( + 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_processed_document_flattened_error(): + client = DocumentServiceClient( + 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_processed_document( + document_service.GetProcessedDocumentRequest(), + name="name_value", + ) + + +@pytest.mark.asyncio +async def test_get_processed_document_flattened_async(): + client = DocumentServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.get_processed_document), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = document.ProcessedDocument() + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + document.ProcessedDocument() + ) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.get_processed_document( + 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_processed_document_flattened_error_async(): + client = DocumentServiceAsyncClient( + 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_processed_document( + document_service.GetProcessedDocumentRequest(), + name="name_value", + ) + + @pytest.mark.parametrize( "request_type", [ @@ -5436,6 +5738,300 @@ def test_purge_documents_rest_error(): ) +@pytest.mark.parametrize( + "request_type", + [ + document_service.GetProcessedDocumentRequest, + dict, + ], +) +def test_get_processed_document_rest(request_type): + client = DocumentServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = { + "name": "projects/sample1/locations/sample2/dataStores/sample3/branches/sample4/documents/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 = document.ProcessedDocument( + document="document_value", + json_data="json_data_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 = document.ProcessedDocument.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_processed_document(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, document.ProcessedDocument) + assert response.document == "document_value" + + +def test_get_processed_document_rest_required_fields( + request_type=document_service.GetProcessedDocumentRequest, +): + transport_class = transports.DocumentServiceRestTransport + + 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_processed_document._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_processed_document._get_unset_required_fields(jsonified_request) + # Check that path parameters and body parameters are not mixing in. + assert not set(unset_fields) - set( + ( + "processed_document_format", + "processed_document_type", + ) + ) + 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 = DocumentServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = document.ProcessedDocument() + # 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 = document.ProcessedDocument.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_processed_document(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_get_processed_document_rest_unset_required_fields(): + transport = transports.DocumentServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.get_processed_document._get_unset_required_fields({}) + assert set(unset_fields) == ( + set( + ( + "processedDocumentFormat", + "processedDocumentType", + ) + ) + & set( + ( + "name", + "processedDocumentType", + ) + ) + ) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_get_processed_document_rest_interceptors(null_interceptor): + transport = transports.DocumentServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.DocumentServiceRestInterceptor(), + ) + client = DocumentServiceClient(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.DocumentServiceRestInterceptor, "post_get_processed_document" + ) as post, mock.patch.object( + transports.DocumentServiceRestInterceptor, "pre_get_processed_document" + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = document_service.GetProcessedDocumentRequest.pb( + document_service.GetProcessedDocumentRequest() + ) + 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 = document.ProcessedDocument.to_json( + document.ProcessedDocument() + ) + + request = document_service.GetProcessedDocumentRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = document.ProcessedDocument() + + client.get_processed_document( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_get_processed_document_rest_bad_request( + transport: str = "rest", request_type=document_service.GetProcessedDocumentRequest +): + client = DocumentServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = { + "name": "projects/sample1/locations/sample2/dataStores/sample3/branches/sample4/documents/sample5" + } + 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_processed_document(request) + + +def test_get_processed_document_rest_flattened(): + client = DocumentServiceClient( + 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 = document.ProcessedDocument() + + # get arguments that satisfy an http rule for this method + sample_request = { + "name": "projects/sample1/locations/sample2/dataStores/sample3/branches/sample4/documents/sample5" + } + + # 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 = document.ProcessedDocument.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_processed_document(**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/v1alpha/{name=projects/*/locations/*/dataStores/*/branches/*/documents/*}:getProcessedDocument" + % client.transport._host, + args[1], + ) + + +def test_get_processed_document_rest_flattened_error(transport: str = "rest"): + client = DocumentServiceClient( + 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_processed_document( + document_service.GetProcessedDocumentRequest(), + name="name_value", + ) + + +def test_get_processed_document_rest_error(): + client = DocumentServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + def test_credentials_transport_error(): # It is an error to provide credentials and a transport instance. transport = transports.DocumentServiceGrpcTransport( @@ -5582,6 +6178,7 @@ def test_document_service_base_transport(): "delete_document", "import_documents", "purge_documents", + "get_processed_document", "get_operation", "list_operations", ) @@ -5885,6 +6482,9 @@ def test_document_service_client_transport_session_collision(transport_name): session1 = client1.transport.purge_documents._session session2 = client2.transport.purge_documents._session assert session1 != session2 + session1 = client1.transport.get_processed_document._session + session2 = client2.transport.get_processed_document._session + assert session1 != session2 def test_document_service_grpc_transport_channel(): @@ -6110,8 +6710,39 @@ def test_parse_document_path(): assert expected == actual +def test_fhir_store_path(): + project = "cuttlefish" + location = "mussel" + dataset = "winkle" + fhir_store = "nautilus" + expected = "projects/{project}/locations/{location}/datasets/{dataset}/fhirStores/{fhir_store}".format( + project=project, + location=location, + dataset=dataset, + fhir_store=fhir_store, + ) + actual = DocumentServiceClient.fhir_store_path( + project, location, dataset, fhir_store + ) + assert expected == actual + + +def test_parse_fhir_store_path(): + expected = { + "project": "scallop", + "location": "abalone", + "dataset": "squid", + "fhir_store": "clam", + } + path = DocumentServiceClient.fhir_store_path(**expected) + + # Check that the path construction is reversible. + actual = DocumentServiceClient.parse_fhir_store_path(path) + assert expected == actual + + def test_common_billing_account_path(): - billing_account = "cuttlefish" + billing_account = "whelk" expected = "billingAccounts/{billing_account}".format( billing_account=billing_account, ) @@ -6121,7 +6752,7 @@ def test_common_billing_account_path(): def test_parse_common_billing_account_path(): expected = { - "billing_account": "mussel", + "billing_account": "octopus", } path = DocumentServiceClient.common_billing_account_path(**expected) @@ -6131,7 +6762,7 @@ def test_parse_common_billing_account_path(): def test_common_folder_path(): - folder = "winkle" + folder = "oyster" expected = "folders/{folder}".format( folder=folder, ) @@ -6141,7 +6772,7 @@ def test_common_folder_path(): def test_parse_common_folder_path(): expected = { - "folder": "nautilus", + "folder": "nudibranch", } path = DocumentServiceClient.common_folder_path(**expected) @@ -6151,7 +6782,7 @@ def test_parse_common_folder_path(): def test_common_organization_path(): - organization = "scallop" + organization = "cuttlefish" expected = "organizations/{organization}".format( organization=organization, ) @@ -6161,7 +6792,7 @@ def test_common_organization_path(): def test_parse_common_organization_path(): expected = { - "organization": "abalone", + "organization": "mussel", } path = DocumentServiceClient.common_organization_path(**expected) @@ -6171,7 +6802,7 @@ def test_parse_common_organization_path(): def test_common_project_path(): - project = "squid" + project = "winkle" expected = "projects/{project}".format( project=project, ) @@ -6181,7 +6812,7 @@ def test_common_project_path(): def test_parse_common_project_path(): expected = { - "project": "clam", + "project": "nautilus", } path = DocumentServiceClient.common_project_path(**expected) @@ -6191,8 +6822,8 @@ def test_parse_common_project_path(): def test_common_location_path(): - project = "whelk" - location = "octopus" + project = "scallop" + location = "abalone" expected = "projects/{project}/locations/{location}".format( project=project, location=location, @@ -6203,8 +6834,8 @@ def test_common_location_path(): def test_parse_common_location_path(): expected = { - "project": "oyster", - "location": "nudibranch", + "project": "squid", + "location": "clam", } path = DocumentServiceClient.common_location_path(**expected) diff --git a/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1alpha/test_grounded_generation_service.py b/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1alpha/test_grounded_generation_service.py new file mode 100644 index 000000000000..9a6b3166ad0c --- /dev/null +++ b/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1alpha/test_grounded_generation_service.py @@ -0,0 +1,2824 @@ +# -*- 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 +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 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.discoveryengine_v1alpha.services.grounded_generation_service import ( + GroundedGenerationServiceAsyncClient, + GroundedGenerationServiceClient, + transports, +) +from google.cloud.discoveryengine_v1alpha.types import ( + grounded_generation_service, + grounding, +) + + +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 GroundedGenerationServiceClient._get_default_mtls_endpoint(None) is None + assert ( + GroundedGenerationServiceClient._get_default_mtls_endpoint(api_endpoint) + == api_mtls_endpoint + ) + assert ( + GroundedGenerationServiceClient._get_default_mtls_endpoint(api_mtls_endpoint) + == api_mtls_endpoint + ) + assert ( + GroundedGenerationServiceClient._get_default_mtls_endpoint(sandbox_endpoint) + == sandbox_mtls_endpoint + ) + assert ( + GroundedGenerationServiceClient._get_default_mtls_endpoint( + sandbox_mtls_endpoint + ) + == sandbox_mtls_endpoint + ) + assert ( + GroundedGenerationServiceClient._get_default_mtls_endpoint(non_googleapi) + == non_googleapi + ) + + +def test__read_environment_variables(): + assert GroundedGenerationServiceClient._read_environment_variables() == ( + False, + "auto", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "true"}): + assert GroundedGenerationServiceClient._read_environment_variables() == ( + True, + "auto", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "false"}): + assert GroundedGenerationServiceClient._read_environment_variables() == ( + False, + "auto", + None, + ) + + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"} + ): + with pytest.raises(ValueError) as excinfo: + GroundedGenerationServiceClient._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 GroundedGenerationServiceClient._read_environment_variables() == ( + False, + "never", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): + assert GroundedGenerationServiceClient._read_environment_variables() == ( + False, + "always", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "auto"}): + assert GroundedGenerationServiceClient._read_environment_variables() == ( + False, + "auto", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "Unsupported"}): + with pytest.raises(MutualTLSChannelError) as excinfo: + GroundedGenerationServiceClient._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 GroundedGenerationServiceClient._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 GroundedGenerationServiceClient._get_client_cert_source(None, False) is None + assert ( + GroundedGenerationServiceClient._get_client_cert_source( + mock_provided_cert_source, False + ) + is None + ) + assert ( + GroundedGenerationServiceClient._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 ( + GroundedGenerationServiceClient._get_client_cert_source(None, True) + is mock_default_cert_source + ) + assert ( + GroundedGenerationServiceClient._get_client_cert_source( + mock_provided_cert_source, "true" + ) + is mock_provided_cert_source + ) + + +@mock.patch.object( + GroundedGenerationServiceClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(GroundedGenerationServiceClient), +) +@mock.patch.object( + GroundedGenerationServiceAsyncClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(GroundedGenerationServiceAsyncClient), +) +def test__get_api_endpoint(): + api_override = "foo.com" + mock_client_cert_source = mock.Mock() + default_universe = GroundedGenerationServiceClient._DEFAULT_UNIVERSE + default_endpoint = ( + GroundedGenerationServiceClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=default_universe + ) + ) + mock_universe = "bar.com" + mock_endpoint = GroundedGenerationServiceClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=mock_universe + ) + + assert ( + GroundedGenerationServiceClient._get_api_endpoint( + api_override, mock_client_cert_source, default_universe, "always" + ) + == api_override + ) + assert ( + GroundedGenerationServiceClient._get_api_endpoint( + None, mock_client_cert_source, default_universe, "auto" + ) + == GroundedGenerationServiceClient.DEFAULT_MTLS_ENDPOINT + ) + assert ( + GroundedGenerationServiceClient._get_api_endpoint( + None, None, default_universe, "auto" + ) + == default_endpoint + ) + assert ( + GroundedGenerationServiceClient._get_api_endpoint( + None, None, default_universe, "always" + ) + == GroundedGenerationServiceClient.DEFAULT_MTLS_ENDPOINT + ) + assert ( + GroundedGenerationServiceClient._get_api_endpoint( + None, mock_client_cert_source, default_universe, "always" + ) + == GroundedGenerationServiceClient.DEFAULT_MTLS_ENDPOINT + ) + assert ( + GroundedGenerationServiceClient._get_api_endpoint( + None, None, mock_universe, "never" + ) + == mock_endpoint + ) + assert ( + GroundedGenerationServiceClient._get_api_endpoint( + None, None, default_universe, "never" + ) + == default_endpoint + ) + + with pytest.raises(MutualTLSChannelError) as excinfo: + GroundedGenerationServiceClient._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 ( + GroundedGenerationServiceClient._get_universe_domain( + client_universe_domain, universe_domain_env + ) + == client_universe_domain + ) + assert ( + GroundedGenerationServiceClient._get_universe_domain(None, universe_domain_env) + == universe_domain_env + ) + assert ( + GroundedGenerationServiceClient._get_universe_domain(None, None) + == GroundedGenerationServiceClient._DEFAULT_UNIVERSE + ) + + with pytest.raises(ValueError) as excinfo: + GroundedGenerationServiceClient._get_universe_domain("", None) + assert str(excinfo.value) == "Universe Domain cannot be an empty string." + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name", + [ + ( + GroundedGenerationServiceClient, + transports.GroundedGenerationServiceGrpcTransport, + "grpc", + ), + ( + GroundedGenerationServiceClient, + transports.GroundedGenerationServiceRestTransport, + "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", + [ + (GroundedGenerationServiceClient, "grpc"), + (GroundedGenerationServiceAsyncClient, "grpc_asyncio"), + (GroundedGenerationServiceClient, "rest"), + ], +) +def test_grounded_generation_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 == ( + "discoveryengine.googleapis.com:443" + if transport_name in ["grpc", "grpc_asyncio"] + else "https://discoveryengine.googleapis.com" + ) + + +@pytest.mark.parametrize( + "transport_class,transport_name", + [ + (transports.GroundedGenerationServiceGrpcTransport, "grpc"), + (transports.GroundedGenerationServiceGrpcAsyncIOTransport, "grpc_asyncio"), + (transports.GroundedGenerationServiceRestTransport, "rest"), + ], +) +def test_grounded_generation_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", + [ + (GroundedGenerationServiceClient, "grpc"), + (GroundedGenerationServiceAsyncClient, "grpc_asyncio"), + (GroundedGenerationServiceClient, "rest"), + ], +) +def test_grounded_generation_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 == ( + "discoveryengine.googleapis.com:443" + if transport_name in ["grpc", "grpc_asyncio"] + else "https://discoveryengine.googleapis.com" + ) + + +def test_grounded_generation_service_client_get_transport_class(): + transport = GroundedGenerationServiceClient.get_transport_class() + available_transports = [ + transports.GroundedGenerationServiceGrpcTransport, + transports.GroundedGenerationServiceRestTransport, + ] + assert transport in available_transports + + transport = GroundedGenerationServiceClient.get_transport_class("grpc") + assert transport == transports.GroundedGenerationServiceGrpcTransport + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name", + [ + ( + GroundedGenerationServiceClient, + transports.GroundedGenerationServiceGrpcTransport, + "grpc", + ), + ( + GroundedGenerationServiceAsyncClient, + transports.GroundedGenerationServiceGrpcAsyncIOTransport, + "grpc_asyncio", + ), + ( + GroundedGenerationServiceClient, + transports.GroundedGenerationServiceRestTransport, + "rest", + ), + ], +) +@mock.patch.object( + GroundedGenerationServiceClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(GroundedGenerationServiceClient), +) +@mock.patch.object( + GroundedGenerationServiceAsyncClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(GroundedGenerationServiceAsyncClient), +) +def test_grounded_generation_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( + GroundedGenerationServiceClient, "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( + GroundedGenerationServiceClient, "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", + [ + ( + GroundedGenerationServiceClient, + transports.GroundedGenerationServiceGrpcTransport, + "grpc", + "true", + ), + ( + GroundedGenerationServiceAsyncClient, + transports.GroundedGenerationServiceGrpcAsyncIOTransport, + "grpc_asyncio", + "true", + ), + ( + GroundedGenerationServiceClient, + transports.GroundedGenerationServiceGrpcTransport, + "grpc", + "false", + ), + ( + GroundedGenerationServiceAsyncClient, + transports.GroundedGenerationServiceGrpcAsyncIOTransport, + "grpc_asyncio", + "false", + ), + ( + GroundedGenerationServiceClient, + transports.GroundedGenerationServiceRestTransport, + "rest", + "true", + ), + ( + GroundedGenerationServiceClient, + transports.GroundedGenerationServiceRestTransport, + "rest", + "false", + ), + ], +) +@mock.patch.object( + GroundedGenerationServiceClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(GroundedGenerationServiceClient), +) +@mock.patch.object( + GroundedGenerationServiceAsyncClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(GroundedGenerationServiceAsyncClient), +) +@mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "auto"}) +def test_grounded_generation_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", + [GroundedGenerationServiceClient, GroundedGenerationServiceAsyncClient], +) +@mock.patch.object( + GroundedGenerationServiceClient, + "DEFAULT_ENDPOINT", + modify_default_endpoint(GroundedGenerationServiceClient), +) +@mock.patch.object( + GroundedGenerationServiceAsyncClient, + "DEFAULT_ENDPOINT", + modify_default_endpoint(GroundedGenerationServiceAsyncClient), +) +def test_grounded_generation_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", + [GroundedGenerationServiceClient, GroundedGenerationServiceAsyncClient], +) +@mock.patch.object( + GroundedGenerationServiceClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(GroundedGenerationServiceClient), +) +@mock.patch.object( + GroundedGenerationServiceAsyncClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(GroundedGenerationServiceAsyncClient), +) +def test_grounded_generation_service_client_client_api_endpoint(client_class): + mock_client_cert_source = client_cert_source_callback + api_override = "foo.com" + default_universe = GroundedGenerationServiceClient._DEFAULT_UNIVERSE + default_endpoint = ( + GroundedGenerationServiceClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=default_universe + ) + ) + mock_universe = "bar.com" + mock_endpoint = GroundedGenerationServiceClient._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", + [ + ( + GroundedGenerationServiceClient, + transports.GroundedGenerationServiceGrpcTransport, + "grpc", + ), + ( + GroundedGenerationServiceAsyncClient, + transports.GroundedGenerationServiceGrpcAsyncIOTransport, + "grpc_asyncio", + ), + ( + GroundedGenerationServiceClient, + transports.GroundedGenerationServiceRestTransport, + "rest", + ), + ], +) +def test_grounded_generation_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", + [ + ( + GroundedGenerationServiceClient, + transports.GroundedGenerationServiceGrpcTransport, + "grpc", + grpc_helpers, + ), + ( + GroundedGenerationServiceAsyncClient, + transports.GroundedGenerationServiceGrpcAsyncIOTransport, + "grpc_asyncio", + grpc_helpers_async, + ), + ( + GroundedGenerationServiceClient, + transports.GroundedGenerationServiceRestTransport, + "rest", + None, + ), + ], +) +def test_grounded_generation_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_grounded_generation_service_client_client_options_from_dict(): + with mock.patch( + "google.cloud.discoveryengine_v1alpha.services.grounded_generation_service.transports.GroundedGenerationServiceGrpcTransport.__init__" + ) as grpc_transport: + grpc_transport.return_value = None + client = GroundedGenerationServiceClient( + 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", + [ + ( + GroundedGenerationServiceClient, + transports.GroundedGenerationServiceGrpcTransport, + "grpc", + grpc_helpers, + ), + ( + GroundedGenerationServiceAsyncClient, + transports.GroundedGenerationServiceGrpcAsyncIOTransport, + "grpc_asyncio", + grpc_helpers_async, + ), + ], +) +def test_grounded_generation_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( + "discoveryengine.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="discoveryengine.googleapis.com", + ssl_credentials=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + +@pytest.mark.parametrize( + "request_type", + [ + grounded_generation_service.CheckGroundingRequest, + dict, + ], +) +def test_check_grounding(request_type, transport: str = "grpc"): + client = GroundedGenerationServiceClient( + 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.check_grounding), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grounded_generation_service.CheckGroundingResponse( + support_score=0.1432, + ) + response = client.check_grounding(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = grounded_generation_service.CheckGroundingRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, grounded_generation_service.CheckGroundingResponse) + assert math.isclose(response.support_score, 0.1432, rel_tol=1e-6) + + +def test_check_grounding_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 = GroundedGenerationServiceClient( + 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.check_grounding), "__call__") as call: + client.check_grounding() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == grounded_generation_service.CheckGroundingRequest() + + +def test_check_grounding_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 = GroundedGenerationServiceClient( + 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 = grounded_generation_service.CheckGroundingRequest( + grounding_config="grounding_config_value", + answer_candidate="answer_candidate_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.check_grounding), "__call__") as call: + client.check_grounding(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == grounded_generation_service.CheckGroundingRequest( + grounding_config="grounding_config_value", + answer_candidate="answer_candidate_value", + ) + + +@pytest.mark.asyncio +async def test_check_grounding_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 = GroundedGenerationServiceAsyncClient( + 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.check_grounding), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + grounded_generation_service.CheckGroundingResponse( + support_score=0.1432, + ) + ) + response = await client.check_grounding() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == grounded_generation_service.CheckGroundingRequest() + + +@pytest.mark.asyncio +async def test_check_grounding_async( + transport: str = "grpc_asyncio", + request_type=grounded_generation_service.CheckGroundingRequest, +): + client = GroundedGenerationServiceAsyncClient( + 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.check_grounding), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + grounded_generation_service.CheckGroundingResponse( + support_score=0.1432, + ) + ) + response = await client.check_grounding(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = grounded_generation_service.CheckGroundingRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, grounded_generation_service.CheckGroundingResponse) + assert math.isclose(response.support_score, 0.1432, rel_tol=1e-6) + + +@pytest.mark.asyncio +async def test_check_grounding_async_from_dict(): + await test_check_grounding_async(request_type=dict) + + +def test_check_grounding_field_headers(): + client = GroundedGenerationServiceClient( + 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 = grounded_generation_service.CheckGroundingRequest() + + request.grounding_config = "grounding_config_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.check_grounding), "__call__") as call: + call.return_value = grounded_generation_service.CheckGroundingResponse() + client.check_grounding(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", + "grounding_config=grounding_config_value", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_check_grounding_field_headers_async(): + client = GroundedGenerationServiceAsyncClient( + 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 = grounded_generation_service.CheckGroundingRequest() + + request.grounding_config = "grounding_config_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.check_grounding), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + grounded_generation_service.CheckGroundingResponse() + ) + await client.check_grounding(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", + "grounding_config=grounding_config_value", + ) in kw["metadata"] + + +@pytest.mark.parametrize( + "request_type", + [ + grounded_generation_service.CheckGroundingRequest, + dict, + ], +) +def test_check_grounding_rest(request_type): + client = GroundedGenerationServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = { + "grounding_config": "projects/sample1/locations/sample2/groundingConfigs/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 = grounded_generation_service.CheckGroundingResponse( + support_score=0.1432, + ) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = grounded_generation_service.CheckGroundingResponse.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.check_grounding(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, grounded_generation_service.CheckGroundingResponse) + assert math.isclose(response.support_score, 0.1432, rel_tol=1e-6) + + +def test_check_grounding_rest_required_fields( + request_type=grounded_generation_service.CheckGroundingRequest, +): + transport_class = transports.GroundedGenerationServiceRestTransport + + request_init = {} + request_init["grounding_config"] = "" + 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() + ).check_grounding._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + jsonified_request["groundingConfig"] = "grounding_config_value" + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).check_grounding._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + assert "groundingConfig" in jsonified_request + assert jsonified_request["groundingConfig"] == "grounding_config_value" + + client = GroundedGenerationServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = grounded_generation_service.CheckGroundingResponse() + # 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 = grounded_generation_service.CheckGroundingResponse.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.check_grounding(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_check_grounding_rest_unset_required_fields(): + transport = transports.GroundedGenerationServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.check_grounding._get_unset_required_fields({}) + assert set(unset_fields) == (set(()) & set(("groundingConfig",))) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_check_grounding_rest_interceptors(null_interceptor): + transport = transports.GroundedGenerationServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.GroundedGenerationServiceRestInterceptor(), + ) + client = GroundedGenerationServiceClient(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.GroundedGenerationServiceRestInterceptor, "post_check_grounding" + ) as post, mock.patch.object( + transports.GroundedGenerationServiceRestInterceptor, "pre_check_grounding" + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = grounded_generation_service.CheckGroundingRequest.pb( + grounded_generation_service.CheckGroundingRequest() + ) + 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 = ( + grounded_generation_service.CheckGroundingResponse.to_json( + grounded_generation_service.CheckGroundingResponse() + ) + ) + + request = grounded_generation_service.CheckGroundingRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = grounded_generation_service.CheckGroundingResponse() + + client.check_grounding( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_check_grounding_rest_bad_request( + transport: str = "rest", + request_type=grounded_generation_service.CheckGroundingRequest, +): + client = GroundedGenerationServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = { + "grounding_config": "projects/sample1/locations/sample2/groundingConfigs/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.check_grounding(request) + + +def test_check_grounding_rest_error(): + client = GroundedGenerationServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + +def test_credentials_transport_error(): + # It is an error to provide credentials and a transport instance. + transport = transports.GroundedGenerationServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + with pytest.raises(ValueError): + client = GroundedGenerationServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # It is an error to provide a credentials file and a transport instance. + transport = transports.GroundedGenerationServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + with pytest.raises(ValueError): + client = GroundedGenerationServiceClient( + client_options={"credentials_file": "credentials.json"}, + transport=transport, + ) + + # It is an error to provide an api_key and a transport instance. + transport = transports.GroundedGenerationServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + options = client_options.ClientOptions() + options.api_key = "api_key" + with pytest.raises(ValueError): + client = GroundedGenerationServiceClient( + 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 = GroundedGenerationServiceClient( + client_options=options, credentials=ga_credentials.AnonymousCredentials() + ) + + # It is an error to provide scopes and a transport instance. + transport = transports.GroundedGenerationServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + with pytest.raises(ValueError): + client = GroundedGenerationServiceClient( + client_options={"scopes": ["1", "2"]}, + transport=transport, + ) + + +def test_transport_instance(): + # A client may be instantiated with a custom transport instance. + transport = transports.GroundedGenerationServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + client = GroundedGenerationServiceClient(transport=transport) + assert client.transport is transport + + +def test_transport_get_channel(): + # A client may be instantiated with a custom transport instance. + transport = transports.GroundedGenerationServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + channel = transport.grpc_channel + assert channel + + transport = transports.GroundedGenerationServiceGrpcAsyncIOTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + channel = transport.grpc_channel + assert channel + + +@pytest.mark.parametrize( + "transport_class", + [ + transports.GroundedGenerationServiceGrpcTransport, + transports.GroundedGenerationServiceGrpcAsyncIOTransport, + transports.GroundedGenerationServiceRestTransport, + ], +) +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 = GroundedGenerationServiceClient.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 = GroundedGenerationServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + assert isinstance( + client.transport, + transports.GroundedGenerationServiceGrpcTransport, + ) + + +def test_grounded_generation_service_base_transport_error(): + # Passing both a credentials object and credentials_file should raise an error + with pytest.raises(core_exceptions.DuplicateCredentialArgs): + transport = transports.GroundedGenerationServiceTransport( + credentials=ga_credentials.AnonymousCredentials(), + credentials_file="credentials.json", + ) + + +def test_grounded_generation_service_base_transport(): + # Instantiate the base transport. + with mock.patch( + "google.cloud.discoveryengine_v1alpha.services.grounded_generation_service.transports.GroundedGenerationServiceTransport.__init__" + ) as Transport: + Transport.return_value = None + transport = transports.GroundedGenerationServiceTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Every method on the transport should just blindly + # raise NotImplementedError. + methods = ( + "check_grounding", + "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_grounded_generation_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.discoveryengine_v1alpha.services.grounded_generation_service.transports.GroundedGenerationServiceTransport._prep_wrapped_messages" + ) as Transport: + Transport.return_value = None + load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) + transport = transports.GroundedGenerationServiceTransport( + 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_grounded_generation_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.discoveryengine_v1alpha.services.grounded_generation_service.transports.GroundedGenerationServiceTransport._prep_wrapped_messages" + ) as Transport: + Transport.return_value = None + adc.return_value = (ga_credentials.AnonymousCredentials(), None) + transport = transports.GroundedGenerationServiceTransport() + adc.assert_called_once() + + +def test_grounded_generation_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) + GroundedGenerationServiceClient() + 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.GroundedGenerationServiceGrpcTransport, + transports.GroundedGenerationServiceGrpcAsyncIOTransport, + ], +) +def test_grounded_generation_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.GroundedGenerationServiceGrpcTransport, + transports.GroundedGenerationServiceGrpcAsyncIOTransport, + transports.GroundedGenerationServiceRestTransport, + ], +) +def test_grounded_generation_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.GroundedGenerationServiceGrpcTransport, grpc_helpers), + (transports.GroundedGenerationServiceGrpcAsyncIOTransport, grpc_helpers_async), + ], +) +def test_grounded_generation_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( + "discoveryengine.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="discoveryengine.googleapis.com", + ssl_credentials=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + +@pytest.mark.parametrize( + "transport_class", + [ + transports.GroundedGenerationServiceGrpcTransport, + transports.GroundedGenerationServiceGrpcAsyncIOTransport, + ], +) +def test_grounded_generation_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_grounded_generation_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.GroundedGenerationServiceRestTransport( + 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_grounded_generation_service_host_no_port(transport_name): + client = GroundedGenerationServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + client_options=client_options.ClientOptions( + api_endpoint="discoveryengine.googleapis.com" + ), + transport=transport_name, + ) + assert client.transport._host == ( + "discoveryengine.googleapis.com:443" + if transport_name in ["grpc", "grpc_asyncio"] + else "https://discoveryengine.googleapis.com" + ) + + +@pytest.mark.parametrize( + "transport_name", + [ + "grpc", + "grpc_asyncio", + "rest", + ], +) +def test_grounded_generation_service_host_with_port(transport_name): + client = GroundedGenerationServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + client_options=client_options.ClientOptions( + api_endpoint="discoveryengine.googleapis.com:8000" + ), + transport=transport_name, + ) + assert client.transport._host == ( + "discoveryengine.googleapis.com:8000" + if transport_name in ["grpc", "grpc_asyncio"] + else "https://discoveryengine.googleapis.com:8000" + ) + + +@pytest.mark.parametrize( + "transport_name", + [ + "rest", + ], +) +def test_grounded_generation_service_client_transport_session_collision(transport_name): + creds1 = ga_credentials.AnonymousCredentials() + creds2 = ga_credentials.AnonymousCredentials() + client1 = GroundedGenerationServiceClient( + credentials=creds1, + transport=transport_name, + ) + client2 = GroundedGenerationServiceClient( + credentials=creds2, + transport=transport_name, + ) + session1 = client1.transport.check_grounding._session + session2 = client2.transport.check_grounding._session + assert session1 != session2 + + +def test_grounded_generation_service_grpc_transport_channel(): + channel = grpc.secure_channel("http://localhost/", grpc.local_channel_credentials()) + + # Check that channel is used if provided. + transport = transports.GroundedGenerationServiceGrpcTransport( + 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_grounded_generation_service_grpc_asyncio_transport_channel(): + channel = aio.secure_channel("http://localhost/", grpc.local_channel_credentials()) + + # Check that channel is used if provided. + transport = transports.GroundedGenerationServiceGrpcAsyncIOTransport( + 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.GroundedGenerationServiceGrpcTransport, + transports.GroundedGenerationServiceGrpcAsyncIOTransport, + ], +) +def test_grounded_generation_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.GroundedGenerationServiceGrpcTransport, + transports.GroundedGenerationServiceGrpcAsyncIOTransport, + ], +) +def test_grounded_generation_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_grounding_config_path(): + project = "squid" + location = "clam" + grounding_config = "whelk" + expected = "projects/{project}/locations/{location}/groundingConfigs/{grounding_config}".format( + project=project, + location=location, + grounding_config=grounding_config, + ) + actual = GroundedGenerationServiceClient.grounding_config_path( + project, location, grounding_config + ) + assert expected == actual + + +def test_parse_grounding_config_path(): + expected = { + "project": "octopus", + "location": "oyster", + "grounding_config": "nudibranch", + } + path = GroundedGenerationServiceClient.grounding_config_path(**expected) + + # Check that the path construction is reversible. + actual = GroundedGenerationServiceClient.parse_grounding_config_path(path) + assert expected == actual + + +def test_common_billing_account_path(): + billing_account = "cuttlefish" + expected = "billingAccounts/{billing_account}".format( + billing_account=billing_account, + ) + actual = GroundedGenerationServiceClient.common_billing_account_path( + billing_account + ) + assert expected == actual + + +def test_parse_common_billing_account_path(): + expected = { + "billing_account": "mussel", + } + path = GroundedGenerationServiceClient.common_billing_account_path(**expected) + + # Check that the path construction is reversible. + actual = GroundedGenerationServiceClient.parse_common_billing_account_path(path) + assert expected == actual + + +def test_common_folder_path(): + folder = "winkle" + expected = "folders/{folder}".format( + folder=folder, + ) + actual = GroundedGenerationServiceClient.common_folder_path(folder) + assert expected == actual + + +def test_parse_common_folder_path(): + expected = { + "folder": "nautilus", + } + path = GroundedGenerationServiceClient.common_folder_path(**expected) + + # Check that the path construction is reversible. + actual = GroundedGenerationServiceClient.parse_common_folder_path(path) + assert expected == actual + + +def test_common_organization_path(): + organization = "scallop" + expected = "organizations/{organization}".format( + organization=organization, + ) + actual = GroundedGenerationServiceClient.common_organization_path(organization) + assert expected == actual + + +def test_parse_common_organization_path(): + expected = { + "organization": "abalone", + } + path = GroundedGenerationServiceClient.common_organization_path(**expected) + + # Check that the path construction is reversible. + actual = GroundedGenerationServiceClient.parse_common_organization_path(path) + assert expected == actual + + +def test_common_project_path(): + project = "squid" + expected = "projects/{project}".format( + project=project, + ) + actual = GroundedGenerationServiceClient.common_project_path(project) + assert expected == actual + + +def test_parse_common_project_path(): + expected = { + "project": "clam", + } + path = GroundedGenerationServiceClient.common_project_path(**expected) + + # Check that the path construction is reversible. + actual = GroundedGenerationServiceClient.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 = GroundedGenerationServiceClient.common_location_path(project, location) + assert expected == actual + + +def test_parse_common_location_path(): + expected = { + "project": "oyster", + "location": "nudibranch", + } + path = GroundedGenerationServiceClient.common_location_path(**expected) + + # Check that the path construction is reversible. + actual = GroundedGenerationServiceClient.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.GroundedGenerationServiceTransport, "_prep_wrapped_messages" + ) as prep: + client = GroundedGenerationServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + client_info=client_info, + ) + prep.assert_called_once_with(client_info) + + with mock.patch.object( + transports.GroundedGenerationServiceTransport, "_prep_wrapped_messages" + ) as prep: + transport_class = GroundedGenerationServiceClient.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 = GroundedGenerationServiceAsyncClient( + 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 = GroundedGenerationServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + request = request_type() + request = json_format.ParseDict( + { + "name": "projects/sample1/locations/sample2/collections/sample3/dataConnector/operations/sample4" + }, + 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 = GroundedGenerationServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request_init = { + "name": "projects/sample1/locations/sample2/collections/sample3/dataConnector/operations/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() + + # 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 = GroundedGenerationServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + request = request_type() + request = json_format.ParseDict( + { + "name": "projects/sample1/locations/sample2/collections/sample3/dataConnector" + }, + 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 = GroundedGenerationServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request_init = { + "name": "projects/sample1/locations/sample2/collections/sample3/dataConnector" + } + 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 = GroundedGenerationServiceClient( + 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 = GroundedGenerationServiceAsyncClient( + 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 = GroundedGenerationServiceClient( + 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 = GroundedGenerationServiceAsyncClient( + 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 = GroundedGenerationServiceClient( + 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 = GroundedGenerationServiceAsyncClient( + 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 = GroundedGenerationServiceClient( + 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 = GroundedGenerationServiceAsyncClient( + 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 = GroundedGenerationServiceClient( + 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 = GroundedGenerationServiceAsyncClient( + 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 = GroundedGenerationServiceClient( + 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 = GroundedGenerationServiceAsyncClient( + 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 = GroundedGenerationServiceClient( + 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 = GroundedGenerationServiceClient( + 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", + [ + ( + GroundedGenerationServiceClient, + transports.GroundedGenerationServiceGrpcTransport, + ), + ( + GroundedGenerationServiceAsyncClient, + transports.GroundedGenerationServiceGrpcAsyncIOTransport, + ), + ], +) +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-discoveryengine/tests/unit/gapic/discoveryengine_v1alpha/test_project_service.py b/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1alpha/test_project_service.py new file mode 100644 index 000000000000..0b5ef60054db --- /dev/null +++ b/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1alpha/test_project_service.py @@ -0,0 +1,4100 @@ +# -*- 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 ( + future, + gapic_v1, + grpc_helpers, + grpc_helpers_async, + operation, + operations_v1, + 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 operation_async # type: ignore +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 json_format +from google.protobuf import timestamp_pb2 # type: ignore +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.discoveryengine_v1alpha.services.project_service import ( + ProjectServiceAsyncClient, + ProjectServiceClient, + transports, +) +from google.cloud.discoveryengine_v1alpha.types import project +from google.cloud.discoveryengine_v1alpha.types import project as gcd_project +from google.cloud.discoveryengine_v1alpha.types import 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 == ( + "discoveryengine.googleapis.com:443" + if transport_name in ["grpc", "grpc_asyncio"] + else "https://discoveryengine.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 == ( + "discoveryengine.googleapis.com:443" + if transport_name in ["grpc", "grpc_asyncio"] + else "https://discoveryengine.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.discoveryengine_v1alpha.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( + "discoveryengine.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="discoveryengine.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.GetProjectRequest, + dict, + ], +) +def test_get_project(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_project), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = project.Project( + name="name_value", + ) + response = client.get_project(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = project_service.GetProjectRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, project.Project) + assert response.name == "name_value" + + +def test_get_project_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_project), "__call__") as call: + client.get_project() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == project_service.GetProjectRequest() + + +def test_get_project_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.GetProjectRequest( + name="name_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_project), "__call__") as call: + client.get_project(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == project_service.GetProjectRequest( + name="name_value", + ) + + +@pytest.mark.asyncio +async def test_get_project_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_project), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + project.Project( + name="name_value", + ) + ) + response = await client.get_project() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == project_service.GetProjectRequest() + + +@pytest.mark.asyncio +async def test_get_project_async( + transport: str = "grpc_asyncio", request_type=project_service.GetProjectRequest +): + 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_project), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + project.Project( + name="name_value", + ) + ) + response = await client.get_project(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = project_service.GetProjectRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, project.Project) + assert response.name == "name_value" + + +@pytest.mark.asyncio +async def test_get_project_async_from_dict(): + await test_get_project_async(request_type=dict) + + +def test_get_project_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.GetProjectRequest() + + request.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_project), "__call__") as call: + call.return_value = project.Project() + client.get_project(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_project_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.GetProjectRequest() + + request.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_project), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(project.Project()) + await client.get_project(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_project_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_project), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = project.Project() + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.get_project( + 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_project_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_project( + project_service.GetProjectRequest(), + name="name_value", + ) + + +@pytest.mark.asyncio +async def test_get_project_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_project), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = project.Project() + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(project.Project()) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.get_project( + 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_project_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_project( + project_service.GetProjectRequest(), + name="name_value", + ) + + +@pytest.mark.parametrize( + "request_type", + [ + project_service.ProvisionProjectRequest, + dict, + ], +) +def test_provision_project(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.provision_project), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.Operation(name="operations/spam") + response = client.provision_project(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = project_service.ProvisionProjectRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, future.Future) + + +def test_provision_project_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.provision_project), "__call__" + ) as call: + client.provision_project() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == project_service.ProvisionProjectRequest() + + +def test_provision_project_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.ProvisionProjectRequest( + name="name_value", + data_use_terms_version="data_use_terms_version_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.provision_project), "__call__" + ) as call: + client.provision_project(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == project_service.ProvisionProjectRequest( + name="name_value", + data_use_terms_version="data_use_terms_version_value", + ) + + +@pytest.mark.asyncio +async def test_provision_project_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.provision_project), "__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.provision_project() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == project_service.ProvisionProjectRequest() + + +@pytest.mark.asyncio +async def test_provision_project_async( + transport: str = "grpc_asyncio", + request_type=project_service.ProvisionProjectRequest, +): + 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.provision_project), "__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.provision_project(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = project_service.ProvisionProjectRequest() + 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_provision_project_async_from_dict(): + await test_provision_project_async(request_type=dict) + + +def test_provision_project_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.ProvisionProjectRequest() + + request.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.provision_project), "__call__" + ) as call: + call.return_value = operations_pb2.Operation(name="operations/op") + client.provision_project(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_provision_project_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.ProvisionProjectRequest() + + request.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.provision_project), "__call__" + ) as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/op") + ) + await client.provision_project(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_provision_project_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.provision_project), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.Operation(name="operations/op") + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.provision_project( + 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_provision_project_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.provision_project( + project_service.ProvisionProjectRequest(), + name="name_value", + ) + + +@pytest.mark.asyncio +async def test_provision_project_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.provision_project), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.Operation(name="operations/op") + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/spam") + ) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.provision_project( + 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_provision_project_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.provision_project( + project_service.ProvisionProjectRequest(), + name="name_value", + ) + + +@pytest.mark.parametrize( + "request_type", + [ + project_service.ReportConsentChangeRequest, + dict, + ], +) +def test_report_consent_change(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.report_consent_change), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = gcd_project.Project( + name="name_value", + ) + response = client.report_consent_change(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = project_service.ReportConsentChangeRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, gcd_project.Project) + assert response.name == "name_value" + + +def test_report_consent_change_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.report_consent_change), "__call__" + ) as call: + client.report_consent_change() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == project_service.ReportConsentChangeRequest() + + +def test_report_consent_change_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.ReportConsentChangeRequest( + project="project_value", + service_term_id="service_term_id_value", + service_term_version="service_term_version_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.report_consent_change), "__call__" + ) as call: + client.report_consent_change(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == project_service.ReportConsentChangeRequest( + project="project_value", + service_term_id="service_term_id_value", + service_term_version="service_term_version_value", + ) + + +@pytest.mark.asyncio +async def test_report_consent_change_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.report_consent_change), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + gcd_project.Project( + name="name_value", + ) + ) + response = await client.report_consent_change() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == project_service.ReportConsentChangeRequest() + + +@pytest.mark.asyncio +async def test_report_consent_change_async( + transport: str = "grpc_asyncio", + request_type=project_service.ReportConsentChangeRequest, +): + 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.report_consent_change), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + gcd_project.Project( + name="name_value", + ) + ) + response = await client.report_consent_change(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = project_service.ReportConsentChangeRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, gcd_project.Project) + assert response.name == "name_value" + + +@pytest.mark.asyncio +async def test_report_consent_change_async_from_dict(): + await test_report_consent_change_async(request_type=dict) + + +def test_report_consent_change_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.ReportConsentChangeRequest() + + request.project = "project_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.report_consent_change), "__call__" + ) as call: + call.return_value = gcd_project.Project() + client.report_consent_change(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", + "project=project_value", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_report_consent_change_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.ReportConsentChangeRequest() + + request.project = "project_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.report_consent_change), "__call__" + ) as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(gcd_project.Project()) + await client.report_consent_change(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", + "project=project_value", + ) in kw["metadata"] + + +def test_report_consent_change_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.report_consent_change), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = gcd_project.Project() + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.report_consent_change( + consent_change_action=project_service.ReportConsentChangeRequest.ConsentChangeAction.ACCEPT, + project="project_value", + service_term_id="service_term_id_value", + service_term_version="service_term_version_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].consent_change_action + mock_val = project_service.ReportConsentChangeRequest.ConsentChangeAction.ACCEPT + assert arg == mock_val + arg = args[0].project + mock_val = "project_value" + assert arg == mock_val + arg = args[0].service_term_id + mock_val = "service_term_id_value" + assert arg == mock_val + arg = args[0].service_term_version + mock_val = "service_term_version_value" + assert arg == mock_val + + +def test_report_consent_change_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.report_consent_change( + project_service.ReportConsentChangeRequest(), + consent_change_action=project_service.ReportConsentChangeRequest.ConsentChangeAction.ACCEPT, + project="project_value", + service_term_id="service_term_id_value", + service_term_version="service_term_version_value", + ) + + +@pytest.mark.asyncio +async def test_report_consent_change_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.report_consent_change), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = gcd_project.Project() + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(gcd_project.Project()) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.report_consent_change( + consent_change_action=project_service.ReportConsentChangeRequest.ConsentChangeAction.ACCEPT, + project="project_value", + service_term_id="service_term_id_value", + service_term_version="service_term_version_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].consent_change_action + mock_val = project_service.ReportConsentChangeRequest.ConsentChangeAction.ACCEPT + assert arg == mock_val + arg = args[0].project + mock_val = "project_value" + assert arg == mock_val + arg = args[0].service_term_id + mock_val = "service_term_id_value" + assert arg == mock_val + arg = args[0].service_term_version + mock_val = "service_term_version_value" + assert arg == mock_val + + +@pytest.mark.asyncio +async def test_report_consent_change_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.report_consent_change( + project_service.ReportConsentChangeRequest(), + consent_change_action=project_service.ReportConsentChangeRequest.ConsentChangeAction.ACCEPT, + project="project_value", + service_term_id="service_term_id_value", + service_term_version="service_term_version_value", + ) + + +@pytest.mark.parametrize( + "request_type", + [ + project_service.GetProjectRequest, + dict, + ], +) +def test_get_project_rest(request_type): + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = {"name": "projects/sample1"} + 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.Project( + 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.Project.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_project(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, project.Project) + assert response.name == "name_value" + + +def test_get_project_rest_required_fields( + request_type=project_service.GetProjectRequest, +): + 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_project._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_project._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.Project() + # 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.Project.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_project(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_get_project_rest_unset_required_fields(): + transport = transports.ProjectServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.get_project._get_unset_required_fields({}) + assert set(unset_fields) == (set(()) & set(("name",))) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_get_project_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_project" + ) as post, mock.patch.object( + transports.ProjectServiceRestInterceptor, "pre_get_project" + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = project_service.GetProjectRequest.pb( + project_service.GetProjectRequest() + ) + 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.Project.to_json(project.Project()) + + request = project_service.GetProjectRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = project.Project() + + client.get_project( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_get_project_rest_bad_request( + transport: str = "rest", request_type=project_service.GetProjectRequest +): + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = {"name": "projects/sample1"} + 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_project(request) + + +def test_get_project_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.Project() + + # get arguments that satisfy an http rule for this method + sample_request = {"name": "projects/sample1"} + + # 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.Project.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_project(**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/v1alpha/{name=projects/*}" % client.transport._host, args[1] + ) + + +def test_get_project_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_project( + project_service.GetProjectRequest(), + name="name_value", + ) + + +def test_get_project_rest_error(): + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + +@pytest.mark.parametrize( + "request_type", + [ + project_service.ProvisionProjectRequest, + dict, + ], +) +def test_provision_project_rest(request_type): + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = {"name": "projects/sample1"} + 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.provision_project(request) + + # Establish that the response is the type that we expect. + assert response.operation.name == "operations/spam" + + +def test_provision_project_rest_required_fields( + request_type=project_service.ProvisionProjectRequest, +): + transport_class = transports.ProjectServiceRestTransport + + request_init = {} + request_init["name"] = "" + request_init["accept_data_use_terms"] = False + request_init["data_use_terms_version"] = "" + 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() + ).provision_project._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" + jsonified_request["acceptDataUseTerms"] = True + jsonified_request["dataUseTermsVersion"] = "data_use_terms_version_value" + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).provision_project._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" + assert "acceptDataUseTerms" in jsonified_request + assert jsonified_request["acceptDataUseTerms"] == True + assert "dataUseTermsVersion" in jsonified_request + assert jsonified_request["dataUseTermsVersion"] == "data_use_terms_version_value" + + client = ProjectServiceClient( + 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.provision_project(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_provision_project_rest_unset_required_fields(): + transport = transports.ProjectServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.provision_project._get_unset_required_fields({}) + assert set(unset_fields) == ( + set(()) + & set( + ( + "name", + "acceptDataUseTerms", + "dataUseTermsVersion", + ) + ) + ) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_provision_project_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( + operation.Operation, "_set_result_from_operation" + ), mock.patch.object( + transports.ProjectServiceRestInterceptor, "post_provision_project" + ) as post, mock.patch.object( + transports.ProjectServiceRestInterceptor, "pre_provision_project" + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = project_service.ProvisionProjectRequest.pb( + project_service.ProvisionProjectRequest() + ) + 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 = project_service.ProvisionProjectRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = operations_pb2.Operation() + + client.provision_project( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_provision_project_rest_bad_request( + transport: str = "rest", request_type=project_service.ProvisionProjectRequest +): + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = {"name": "projects/sample1"} + 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.provision_project(request) + + +def test_provision_project_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 = operations_pb2.Operation(name="operations/spam") + + # get arguments that satisfy an http rule for this method + sample_request = {"name": "projects/sample1"} + + # 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 + json_return_value = json_format.MessageToJson(return_value) + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + client.provision_project(**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/v1alpha/{name=projects/*}:provision" % client.transport._host, args[1] + ) + + +def test_provision_project_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.provision_project( + project_service.ProvisionProjectRequest(), + name="name_value", + ) + + +def test_provision_project_rest_error(): + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + +@pytest.mark.parametrize( + "request_type", + [ + project_service.ReportConsentChangeRequest, + dict, + ], +) +def test_report_consent_change_rest(request_type): + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = {"project": "projects/sample1"} + 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 = gcd_project.Project( + 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 = gcd_project.Project.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.report_consent_change(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, gcd_project.Project) + assert response.name == "name_value" + + +def test_report_consent_change_rest_required_fields( + request_type=project_service.ReportConsentChangeRequest, +): + transport_class = transports.ProjectServiceRestTransport + + request_init = {} + request_init["project"] = "" + request_init["service_term_id"] = "" + request_init["service_term_version"] = "" + 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() + ).report_consent_change._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + jsonified_request["project"] = "project_value" + jsonified_request["serviceTermId"] = "service_term_id_value" + jsonified_request["serviceTermVersion"] = "service_term_version_value" + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).report_consent_change._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + assert "project" in jsonified_request + assert jsonified_request["project"] == "project_value" + assert "serviceTermId" in jsonified_request + assert jsonified_request["serviceTermId"] == "service_term_id_value" + assert "serviceTermVersion" in jsonified_request + assert jsonified_request["serviceTermVersion"] == "service_term_version_value" + + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = gcd_project.Project() + # 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 = gcd_project.Project.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.report_consent_change(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_report_consent_change_rest_unset_required_fields(): + transport = transports.ProjectServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.report_consent_change._get_unset_required_fields({}) + assert set(unset_fields) == ( + set(()) + & set( + ( + "consentChangeAction", + "project", + "serviceTermId", + "serviceTermVersion", + ) + ) + ) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_report_consent_change_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_report_consent_change" + ) as post, mock.patch.object( + transports.ProjectServiceRestInterceptor, "pre_report_consent_change" + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = project_service.ReportConsentChangeRequest.pb( + project_service.ReportConsentChangeRequest() + ) + 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 = gcd_project.Project.to_json(gcd_project.Project()) + + request = project_service.ReportConsentChangeRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = gcd_project.Project() + + client.report_consent_change( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_report_consent_change_rest_bad_request( + transport: str = "rest", request_type=project_service.ReportConsentChangeRequest +): + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = {"project": "projects/sample1"} + 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.report_consent_change(request) + + +def test_report_consent_change_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 = gcd_project.Project() + + # get arguments that satisfy an http rule for this method + sample_request = {"project": "projects/sample1"} + + # get truthy value for each flattened field + mock_args = dict( + consent_change_action=project_service.ReportConsentChangeRequest.ConsentChangeAction.ACCEPT, + project="project_value", + service_term_id="service_term_id_value", + service_term_version="service_term_version_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 = gcd_project.Project.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.report_consent_change(**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/v1alpha/{project=projects/*}:reportConsentChange" + % client.transport._host, + args[1], + ) + + +def test_report_consent_change_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.report_consent_change( + project_service.ReportConsentChangeRequest(), + consent_change_action=project_service.ReportConsentChangeRequest.ConsentChangeAction.ACCEPT, + project="project_value", + service_term_id="service_term_id_value", + service_term_version="service_term_version_value", + ) + + +def test_report_consent_change_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.discoveryengine_v1alpha.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_project", + "provision_project", + "report_consent_change", + "get_operation", + "list_operations", + ) + for method in methods: + with pytest.raises(NotImplementedError): + getattr(transport, method)(request=object()) + + with pytest.raises(NotImplementedError): + transport.close() + + # Additionally, the LRO client (a property) should + # also raise NotImplementedError + with pytest.raises(NotImplementedError): + transport.operations_client + + # 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.discoveryengine_v1alpha.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.discoveryengine_v1alpha.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( + "discoveryengine.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="discoveryengine.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) + + +def test_project_service_rest_lro_client(): + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + transport = client.transport + + # Ensure that we have a api-core operations client. + assert isinstance( + transport.operations_client, + operations_v1.AbstractOperationsClient, + ) + + # Ensure that subsequent calls to the property send the exact same object. + assert transport.operations_client is transport.operations_client + + +@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="discoveryengine.googleapis.com" + ), + transport=transport_name, + ) + assert client.transport._host == ( + "discoveryengine.googleapis.com:443" + if transport_name in ["grpc", "grpc_asyncio"] + else "https://discoveryengine.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="discoveryengine.googleapis.com:8000" + ), + transport=transport_name, + ) + assert client.transport._host == ( + "discoveryengine.googleapis.com:8000" + if transport_name in ["grpc", "grpc_asyncio"] + else "https://discoveryengine.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_project._session + session2 = client2.transport.get_project._session + assert session1 != session2 + session1 = client1.transport.provision_project._session + session2 = client2.transport.provision_project._session + assert session1 != session2 + session1 = client1.transport.report_consent_change._session + session2 = client2.transport.report_consent_change._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_project_service_grpc_lro_client(): + client = ProjectServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + transport = client.transport + + # Ensure that we have a api-core operations client. + assert isinstance( + transport.operations_client, + operations_v1.OperationsClient, + ) + + # Ensure that subsequent calls to the property send the exact same object. + assert transport.operations_client is transport.operations_client + + +def test_project_service_grpc_lro_async_client(): + client = ProjectServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc_asyncio", + ) + transport = client.transport + + # Ensure that we have a api-core operations client. + assert isinstance( + transport.operations_client, + operations_v1.OperationsAsyncClient, + ) + + # Ensure that subsequent calls to the property send the exact same object. + assert transport.operations_client is transport.operations_client + + +def test_project_path(): + project = "squid" + expected = "projects/{project}".format( + project=project, + ) + actual = ProjectServiceClient.project_path(project) + assert expected == actual + + +def test_parse_project_path(): + expected = { + "project": "clam", + } + path = ProjectServiceClient.project_path(**expected) + + # Check that the path construction is reversible. + actual = ProjectServiceClient.parse_project_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/collections/sample3/dataConnector/operations/sample4" + }, + 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/collections/sample3/dataConnector/operations/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() + + # 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/collections/sample3/dataConnector" + }, + 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/collections/sample3/dataConnector" + } + 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-discoveryengine/tests/unit/gapic/discoveryengine_v1alpha/test_rank_service.py b/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1alpha/test_rank_service.py new file mode 100644 index 000000000000..969430be6605 --- /dev/null +++ b/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1alpha/test_rank_service.py @@ -0,0 +1,2662 @@ +# -*- 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 +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 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.discoveryengine_v1alpha.services.rank_service import ( + RankServiceAsyncClient, + RankServiceClient, + transports, +) +from google.cloud.discoveryengine_v1alpha.types import rank_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 RankServiceClient._get_default_mtls_endpoint(None) is None + assert ( + RankServiceClient._get_default_mtls_endpoint(api_endpoint) == api_mtls_endpoint + ) + assert ( + RankServiceClient._get_default_mtls_endpoint(api_mtls_endpoint) + == api_mtls_endpoint + ) + assert ( + RankServiceClient._get_default_mtls_endpoint(sandbox_endpoint) + == sandbox_mtls_endpoint + ) + assert ( + RankServiceClient._get_default_mtls_endpoint(sandbox_mtls_endpoint) + == sandbox_mtls_endpoint + ) + assert RankServiceClient._get_default_mtls_endpoint(non_googleapi) == non_googleapi + + +def test__read_environment_variables(): + assert RankServiceClient._read_environment_variables() == (False, "auto", None) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "true"}): + assert RankServiceClient._read_environment_variables() == (True, "auto", None) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "false"}): + assert RankServiceClient._read_environment_variables() == (False, "auto", None) + + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"} + ): + with pytest.raises(ValueError) as excinfo: + RankServiceClient._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 RankServiceClient._read_environment_variables() == (False, "never", None) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): + assert RankServiceClient._read_environment_variables() == ( + False, + "always", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "auto"}): + assert RankServiceClient._read_environment_variables() == (False, "auto", None) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "Unsupported"}): + with pytest.raises(MutualTLSChannelError) as excinfo: + RankServiceClient._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 RankServiceClient._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 RankServiceClient._get_client_cert_source(None, False) is None + assert ( + RankServiceClient._get_client_cert_source(mock_provided_cert_source, False) + is None + ) + assert ( + RankServiceClient._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 ( + RankServiceClient._get_client_cert_source(None, True) + is mock_default_cert_source + ) + assert ( + RankServiceClient._get_client_cert_source( + mock_provided_cert_source, "true" + ) + is mock_provided_cert_source + ) + + +@mock.patch.object( + RankServiceClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(RankServiceClient), +) +@mock.patch.object( + RankServiceAsyncClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(RankServiceAsyncClient), +) +def test__get_api_endpoint(): + api_override = "foo.com" + mock_client_cert_source = mock.Mock() + default_universe = RankServiceClient._DEFAULT_UNIVERSE + default_endpoint = RankServiceClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=default_universe + ) + mock_universe = "bar.com" + mock_endpoint = RankServiceClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=mock_universe + ) + + assert ( + RankServiceClient._get_api_endpoint( + api_override, mock_client_cert_source, default_universe, "always" + ) + == api_override + ) + assert ( + RankServiceClient._get_api_endpoint( + None, mock_client_cert_source, default_universe, "auto" + ) + == RankServiceClient.DEFAULT_MTLS_ENDPOINT + ) + assert ( + RankServiceClient._get_api_endpoint(None, None, default_universe, "auto") + == default_endpoint + ) + assert ( + RankServiceClient._get_api_endpoint(None, None, default_universe, "always") + == RankServiceClient.DEFAULT_MTLS_ENDPOINT + ) + assert ( + RankServiceClient._get_api_endpoint( + None, mock_client_cert_source, default_universe, "always" + ) + == RankServiceClient.DEFAULT_MTLS_ENDPOINT + ) + assert ( + RankServiceClient._get_api_endpoint(None, None, mock_universe, "never") + == mock_endpoint + ) + assert ( + RankServiceClient._get_api_endpoint(None, None, default_universe, "never") + == default_endpoint + ) + + with pytest.raises(MutualTLSChannelError) as excinfo: + RankServiceClient._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 ( + RankServiceClient._get_universe_domain( + client_universe_domain, universe_domain_env + ) + == client_universe_domain + ) + assert ( + RankServiceClient._get_universe_domain(None, universe_domain_env) + == universe_domain_env + ) + assert ( + RankServiceClient._get_universe_domain(None, None) + == RankServiceClient._DEFAULT_UNIVERSE + ) + + with pytest.raises(ValueError) as excinfo: + RankServiceClient._get_universe_domain("", None) + assert str(excinfo.value) == "Universe Domain cannot be an empty string." + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name", + [ + (RankServiceClient, transports.RankServiceGrpcTransport, "grpc"), + (RankServiceClient, transports.RankServiceRestTransport, "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", + [ + (RankServiceClient, "grpc"), + (RankServiceAsyncClient, "grpc_asyncio"), + (RankServiceClient, "rest"), + ], +) +def test_rank_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 == ( + "discoveryengine.googleapis.com:443" + if transport_name in ["grpc", "grpc_asyncio"] + else "https://discoveryengine.googleapis.com" + ) + + +@pytest.mark.parametrize( + "transport_class,transport_name", + [ + (transports.RankServiceGrpcTransport, "grpc"), + (transports.RankServiceGrpcAsyncIOTransport, "grpc_asyncio"), + (transports.RankServiceRestTransport, "rest"), + ], +) +def test_rank_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", + [ + (RankServiceClient, "grpc"), + (RankServiceAsyncClient, "grpc_asyncio"), + (RankServiceClient, "rest"), + ], +) +def test_rank_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 == ( + "discoveryengine.googleapis.com:443" + if transport_name in ["grpc", "grpc_asyncio"] + else "https://discoveryengine.googleapis.com" + ) + + +def test_rank_service_client_get_transport_class(): + transport = RankServiceClient.get_transport_class() + available_transports = [ + transports.RankServiceGrpcTransport, + transports.RankServiceRestTransport, + ] + assert transport in available_transports + + transport = RankServiceClient.get_transport_class("grpc") + assert transport == transports.RankServiceGrpcTransport + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name", + [ + (RankServiceClient, transports.RankServiceGrpcTransport, "grpc"), + ( + RankServiceAsyncClient, + transports.RankServiceGrpcAsyncIOTransport, + "grpc_asyncio", + ), + (RankServiceClient, transports.RankServiceRestTransport, "rest"), + ], +) +@mock.patch.object( + RankServiceClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(RankServiceClient), +) +@mock.patch.object( + RankServiceAsyncClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(RankServiceAsyncClient), +) +def test_rank_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(RankServiceClient, "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(RankServiceClient, "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", + [ + (RankServiceClient, transports.RankServiceGrpcTransport, "grpc", "true"), + ( + RankServiceAsyncClient, + transports.RankServiceGrpcAsyncIOTransport, + "grpc_asyncio", + "true", + ), + (RankServiceClient, transports.RankServiceGrpcTransport, "grpc", "false"), + ( + RankServiceAsyncClient, + transports.RankServiceGrpcAsyncIOTransport, + "grpc_asyncio", + "false", + ), + (RankServiceClient, transports.RankServiceRestTransport, "rest", "true"), + (RankServiceClient, transports.RankServiceRestTransport, "rest", "false"), + ], +) +@mock.patch.object( + RankServiceClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(RankServiceClient), +) +@mock.patch.object( + RankServiceAsyncClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(RankServiceAsyncClient), +) +@mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "auto"}) +def test_rank_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", [RankServiceClient, RankServiceAsyncClient]) +@mock.patch.object( + RankServiceClient, "DEFAULT_ENDPOINT", modify_default_endpoint(RankServiceClient) +) +@mock.patch.object( + RankServiceAsyncClient, + "DEFAULT_ENDPOINT", + modify_default_endpoint(RankServiceAsyncClient), +) +def test_rank_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", [RankServiceClient, RankServiceAsyncClient]) +@mock.patch.object( + RankServiceClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(RankServiceClient), +) +@mock.patch.object( + RankServiceAsyncClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(RankServiceAsyncClient), +) +def test_rank_service_client_client_api_endpoint(client_class): + mock_client_cert_source = client_cert_source_callback + api_override = "foo.com" + default_universe = RankServiceClient._DEFAULT_UNIVERSE + default_endpoint = RankServiceClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=default_universe + ) + mock_universe = "bar.com" + mock_endpoint = RankServiceClient._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", + [ + (RankServiceClient, transports.RankServiceGrpcTransport, "grpc"), + ( + RankServiceAsyncClient, + transports.RankServiceGrpcAsyncIOTransport, + "grpc_asyncio", + ), + (RankServiceClient, transports.RankServiceRestTransport, "rest"), + ], +) +def test_rank_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", + [ + (RankServiceClient, transports.RankServiceGrpcTransport, "grpc", grpc_helpers), + ( + RankServiceAsyncClient, + transports.RankServiceGrpcAsyncIOTransport, + "grpc_asyncio", + grpc_helpers_async, + ), + (RankServiceClient, transports.RankServiceRestTransport, "rest", None), + ], +) +def test_rank_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_rank_service_client_client_options_from_dict(): + with mock.patch( + "google.cloud.discoveryengine_v1alpha.services.rank_service.transports.RankServiceGrpcTransport.__init__" + ) as grpc_transport: + grpc_transport.return_value = None + client = RankServiceClient(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", + [ + (RankServiceClient, transports.RankServiceGrpcTransport, "grpc", grpc_helpers), + ( + RankServiceAsyncClient, + transports.RankServiceGrpcAsyncIOTransport, + "grpc_asyncio", + grpc_helpers_async, + ), + ], +) +def test_rank_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( + "discoveryengine.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="discoveryengine.googleapis.com", + ssl_credentials=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + +@pytest.mark.parametrize( + "request_type", + [ + rank_service.RankRequest, + dict, + ], +) +def test_rank(request_type, transport: str = "grpc"): + client = RankServiceClient( + 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.rank), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = rank_service.RankResponse() + response = client.rank(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = rank_service.RankRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, rank_service.RankResponse) + + +def test_rank_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 = RankServiceClient( + 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.rank), "__call__") as call: + client.rank() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == rank_service.RankRequest() + + +def test_rank_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 = RankServiceClient( + 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 = rank_service.RankRequest( + ranking_config="ranking_config_value", + model="model_value", + query="query_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.rank), "__call__") as call: + client.rank(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == rank_service.RankRequest( + ranking_config="ranking_config_value", + model="model_value", + query="query_value", + ) + + +@pytest.mark.asyncio +async def test_rank_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 = RankServiceAsyncClient( + 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.rank), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + rank_service.RankResponse() + ) + response = await client.rank() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == rank_service.RankRequest() + + +@pytest.mark.asyncio +async def test_rank_async( + transport: str = "grpc_asyncio", request_type=rank_service.RankRequest +): + client = RankServiceAsyncClient( + 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.rank), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + rank_service.RankResponse() + ) + response = await client.rank(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = rank_service.RankRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, rank_service.RankResponse) + + +@pytest.mark.asyncio +async def test_rank_async_from_dict(): + await test_rank_async(request_type=dict) + + +def test_rank_field_headers(): + client = RankServiceClient( + 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 = rank_service.RankRequest() + + request.ranking_config = "ranking_config_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.rank), "__call__") as call: + call.return_value = rank_service.RankResponse() + client.rank(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", + "ranking_config=ranking_config_value", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_rank_field_headers_async(): + client = RankServiceAsyncClient( + 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 = rank_service.RankRequest() + + request.ranking_config = "ranking_config_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.rank), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + rank_service.RankResponse() + ) + await client.rank(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", + "ranking_config=ranking_config_value", + ) in kw["metadata"] + + +@pytest.mark.parametrize( + "request_type", + [ + rank_service.RankRequest, + dict, + ], +) +def test_rank_rest(request_type): + client = RankServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = { + "ranking_config": "projects/sample1/locations/sample2/rankingConfigs/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 = rank_service.RankResponse() + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = rank_service.RankResponse.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.rank(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, rank_service.RankResponse) + + +def test_rank_rest_required_fields(request_type=rank_service.RankRequest): + transport_class = transports.RankServiceRestTransport + + request_init = {} + request_init["ranking_config"] = "" + 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() + ).rank._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + jsonified_request["rankingConfig"] = "ranking_config_value" + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).rank._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + assert "rankingConfig" in jsonified_request + assert jsonified_request["rankingConfig"] == "ranking_config_value" + + client = RankServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = rank_service.RankResponse() + # 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 = rank_service.RankResponse.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.rank(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_rank_rest_unset_required_fields(): + transport = transports.RankServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.rank._get_unset_required_fields({}) + assert set(unset_fields) == ( + set(()) + & set( + ( + "rankingConfig", + "records", + ) + ) + ) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_rank_rest_interceptors(null_interceptor): + transport = transports.RankServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.RankServiceRestInterceptor(), + ) + client = RankServiceClient(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.RankServiceRestInterceptor, "post_rank" + ) as post, mock.patch.object( + transports.RankServiceRestInterceptor, "pre_rank" + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = rank_service.RankRequest.pb(rank_service.RankRequest()) + 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 = rank_service.RankResponse.to_json( + rank_service.RankResponse() + ) + + request = rank_service.RankRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = rank_service.RankResponse() + + client.rank( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_rank_rest_bad_request( + transport: str = "rest", request_type=rank_service.RankRequest +): + client = RankServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = { + "ranking_config": "projects/sample1/locations/sample2/rankingConfigs/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.rank(request) + + +def test_rank_rest_error(): + client = RankServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + +def test_credentials_transport_error(): + # It is an error to provide credentials and a transport instance. + transport = transports.RankServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + with pytest.raises(ValueError): + client = RankServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # It is an error to provide a credentials file and a transport instance. + transport = transports.RankServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + with pytest.raises(ValueError): + client = RankServiceClient( + client_options={"credentials_file": "credentials.json"}, + transport=transport, + ) + + # It is an error to provide an api_key and a transport instance. + transport = transports.RankServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + options = client_options.ClientOptions() + options.api_key = "api_key" + with pytest.raises(ValueError): + client = RankServiceClient( + 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 = RankServiceClient( + client_options=options, credentials=ga_credentials.AnonymousCredentials() + ) + + # It is an error to provide scopes and a transport instance. + transport = transports.RankServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + with pytest.raises(ValueError): + client = RankServiceClient( + client_options={"scopes": ["1", "2"]}, + transport=transport, + ) + + +def test_transport_instance(): + # A client may be instantiated with a custom transport instance. + transport = transports.RankServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + client = RankServiceClient(transport=transport) + assert client.transport is transport + + +def test_transport_get_channel(): + # A client may be instantiated with a custom transport instance. + transport = transports.RankServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + channel = transport.grpc_channel + assert channel + + transport = transports.RankServiceGrpcAsyncIOTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + channel = transport.grpc_channel + assert channel + + +@pytest.mark.parametrize( + "transport_class", + [ + transports.RankServiceGrpcTransport, + transports.RankServiceGrpcAsyncIOTransport, + transports.RankServiceRestTransport, + ], +) +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 = RankServiceClient.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 = RankServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + assert isinstance( + client.transport, + transports.RankServiceGrpcTransport, + ) + + +def test_rank_service_base_transport_error(): + # Passing both a credentials object and credentials_file should raise an error + with pytest.raises(core_exceptions.DuplicateCredentialArgs): + transport = transports.RankServiceTransport( + credentials=ga_credentials.AnonymousCredentials(), + credentials_file="credentials.json", + ) + + +def test_rank_service_base_transport(): + # Instantiate the base transport. + with mock.patch( + "google.cloud.discoveryengine_v1alpha.services.rank_service.transports.RankServiceTransport.__init__" + ) as Transport: + Transport.return_value = None + transport = transports.RankServiceTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Every method on the transport should just blindly + # raise NotImplementedError. + methods = ( + "rank", + "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_rank_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.discoveryengine_v1alpha.services.rank_service.transports.RankServiceTransport._prep_wrapped_messages" + ) as Transport: + Transport.return_value = None + load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) + transport = transports.RankServiceTransport( + 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_rank_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.discoveryengine_v1alpha.services.rank_service.transports.RankServiceTransport._prep_wrapped_messages" + ) as Transport: + Transport.return_value = None + adc.return_value = (ga_credentials.AnonymousCredentials(), None) + transport = transports.RankServiceTransport() + adc.assert_called_once() + + +def test_rank_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) + RankServiceClient() + 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.RankServiceGrpcTransport, + transports.RankServiceGrpcAsyncIOTransport, + ], +) +def test_rank_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.RankServiceGrpcTransport, + transports.RankServiceGrpcAsyncIOTransport, + transports.RankServiceRestTransport, + ], +) +def test_rank_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.RankServiceGrpcTransport, grpc_helpers), + (transports.RankServiceGrpcAsyncIOTransport, grpc_helpers_async), + ], +) +def test_rank_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( + "discoveryengine.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="discoveryengine.googleapis.com", + ssl_credentials=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + +@pytest.mark.parametrize( + "transport_class", + [transports.RankServiceGrpcTransport, transports.RankServiceGrpcAsyncIOTransport], +) +def test_rank_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_rank_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.RankServiceRestTransport( + 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_rank_service_host_no_port(transport_name): + client = RankServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + client_options=client_options.ClientOptions( + api_endpoint="discoveryengine.googleapis.com" + ), + transport=transport_name, + ) + assert client.transport._host == ( + "discoveryengine.googleapis.com:443" + if transport_name in ["grpc", "grpc_asyncio"] + else "https://discoveryengine.googleapis.com" + ) + + +@pytest.mark.parametrize( + "transport_name", + [ + "grpc", + "grpc_asyncio", + "rest", + ], +) +def test_rank_service_host_with_port(transport_name): + client = RankServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + client_options=client_options.ClientOptions( + api_endpoint="discoveryengine.googleapis.com:8000" + ), + transport=transport_name, + ) + assert client.transport._host == ( + "discoveryengine.googleapis.com:8000" + if transport_name in ["grpc", "grpc_asyncio"] + else "https://discoveryengine.googleapis.com:8000" + ) + + +@pytest.mark.parametrize( + "transport_name", + [ + "rest", + ], +) +def test_rank_service_client_transport_session_collision(transport_name): + creds1 = ga_credentials.AnonymousCredentials() + creds2 = ga_credentials.AnonymousCredentials() + client1 = RankServiceClient( + credentials=creds1, + transport=transport_name, + ) + client2 = RankServiceClient( + credentials=creds2, + transport=transport_name, + ) + session1 = client1.transport.rank._session + session2 = client2.transport.rank._session + assert session1 != session2 + + +def test_rank_service_grpc_transport_channel(): + channel = grpc.secure_channel("http://localhost/", grpc.local_channel_credentials()) + + # Check that channel is used if provided. + transport = transports.RankServiceGrpcTransport( + 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_rank_service_grpc_asyncio_transport_channel(): + channel = aio.secure_channel("http://localhost/", grpc.local_channel_credentials()) + + # Check that channel is used if provided. + transport = transports.RankServiceGrpcAsyncIOTransport( + 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.RankServiceGrpcTransport, transports.RankServiceGrpcAsyncIOTransport], +) +def test_rank_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.RankServiceGrpcTransport, transports.RankServiceGrpcAsyncIOTransport], +) +def test_rank_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_ranking_config_path(): + project = "squid" + location = "clam" + ranking_config = "whelk" + expected = "projects/{project}/locations/{location}/rankingConfigs/{ranking_config}".format( + project=project, + location=location, + ranking_config=ranking_config, + ) + actual = RankServiceClient.ranking_config_path(project, location, ranking_config) + assert expected == actual + + +def test_parse_ranking_config_path(): + expected = { + "project": "octopus", + "location": "oyster", + "ranking_config": "nudibranch", + } + path = RankServiceClient.ranking_config_path(**expected) + + # Check that the path construction is reversible. + actual = RankServiceClient.parse_ranking_config_path(path) + assert expected == actual + + +def test_common_billing_account_path(): + billing_account = "cuttlefish" + expected = "billingAccounts/{billing_account}".format( + billing_account=billing_account, + ) + actual = RankServiceClient.common_billing_account_path(billing_account) + assert expected == actual + + +def test_parse_common_billing_account_path(): + expected = { + "billing_account": "mussel", + } + path = RankServiceClient.common_billing_account_path(**expected) + + # Check that the path construction is reversible. + actual = RankServiceClient.parse_common_billing_account_path(path) + assert expected == actual + + +def test_common_folder_path(): + folder = "winkle" + expected = "folders/{folder}".format( + folder=folder, + ) + actual = RankServiceClient.common_folder_path(folder) + assert expected == actual + + +def test_parse_common_folder_path(): + expected = { + "folder": "nautilus", + } + path = RankServiceClient.common_folder_path(**expected) + + # Check that the path construction is reversible. + actual = RankServiceClient.parse_common_folder_path(path) + assert expected == actual + + +def test_common_organization_path(): + organization = "scallop" + expected = "organizations/{organization}".format( + organization=organization, + ) + actual = RankServiceClient.common_organization_path(organization) + assert expected == actual + + +def test_parse_common_organization_path(): + expected = { + "organization": "abalone", + } + path = RankServiceClient.common_organization_path(**expected) + + # Check that the path construction is reversible. + actual = RankServiceClient.parse_common_organization_path(path) + assert expected == actual + + +def test_common_project_path(): + project = "squid" + expected = "projects/{project}".format( + project=project, + ) + actual = RankServiceClient.common_project_path(project) + assert expected == actual + + +def test_parse_common_project_path(): + expected = { + "project": "clam", + } + path = RankServiceClient.common_project_path(**expected) + + # Check that the path construction is reversible. + actual = RankServiceClient.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 = RankServiceClient.common_location_path(project, location) + assert expected == actual + + +def test_parse_common_location_path(): + expected = { + "project": "oyster", + "location": "nudibranch", + } + path = RankServiceClient.common_location_path(**expected) + + # Check that the path construction is reversible. + actual = RankServiceClient.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.RankServiceTransport, "_prep_wrapped_messages" + ) as prep: + client = RankServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + client_info=client_info, + ) + prep.assert_called_once_with(client_info) + + with mock.patch.object( + transports.RankServiceTransport, "_prep_wrapped_messages" + ) as prep: + transport_class = RankServiceClient.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 = RankServiceAsyncClient( + 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 = RankServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + request = request_type() + request = json_format.ParseDict( + { + "name": "projects/sample1/locations/sample2/collections/sample3/dataConnector/operations/sample4" + }, + 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 = RankServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request_init = { + "name": "projects/sample1/locations/sample2/collections/sample3/dataConnector/operations/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() + + # 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 = RankServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + request = request_type() + request = json_format.ParseDict( + { + "name": "projects/sample1/locations/sample2/collections/sample3/dataConnector" + }, + 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 = RankServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request_init = { + "name": "projects/sample1/locations/sample2/collections/sample3/dataConnector" + } + 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 = RankServiceClient( + 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 = RankServiceAsyncClient( + 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 = RankServiceClient( + 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 = RankServiceAsyncClient( + 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 = RankServiceClient( + 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 = RankServiceAsyncClient( + 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 = RankServiceClient( + 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 = RankServiceAsyncClient( + 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 = RankServiceClient( + 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 = RankServiceAsyncClient( + 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 = RankServiceClient( + 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 = RankServiceAsyncClient( + 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 = RankServiceClient( + 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 = RankServiceClient( + 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", + [ + (RankServiceClient, transports.RankServiceGrpcTransport), + (RankServiceAsyncClient, transports.RankServiceGrpcAsyncIOTransport), + ], +) +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-discoveryengine/tests/unit/gapic/discoveryengine_v1alpha/test_schema_service.py b/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1alpha/test_schema_service.py index 6dca9c03b963..38a0444f2f3a 100644 --- a/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1alpha/test_schema_service.py +++ b/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1alpha/test_schema_service.py @@ -3329,6 +3329,7 @@ def test_create_schema_rest(request_type): "completable_option": 1, "recs_filterable_option": 1, "key_property_type": "key_property_type_value", + "advanced_site_search_data_sources": [1], } ], } @@ -3724,6 +3725,7 @@ def test_update_schema_rest(request_type): "completable_option": 1, "recs_filterable_option": 1, "key_property_type": "key_property_type_value", + "advanced_site_search_data_sources": [1], } ], } diff --git a/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1alpha/test_serving_config_service.py b/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1alpha/test_serving_config_service.py index bfc99d86ebed..70ed08b42530 100644 --- a/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1alpha/test_serving_config_service.py +++ b/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1alpha/test_serving_config_service.py @@ -2497,6 +2497,7 @@ def test_update_serving_config_rest(request_type): "model_prompt_spec": {"preamble": "preamble_value"}, "language_code": "language_code_value", "model_spec": {"version": "version_value"}, + "use_semantic_chunks": True, }, "extractive_content_spec": { "max_extractive_answer_count": 2907, @@ -2506,6 +2507,7 @@ def test_update_serving_config_rest(request_type): "num_next_segments": 1843, }, "search_result_mode": 1, + "chunk_spec": {"num_previous_chunks": 2071, "num_next_chunks": 1625}, } }, "name": "projects/sample1/locations/sample2/dataStores/sample3/servingConfigs/sample4", diff --git a/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1beta/test_conversational_search_service.py b/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1beta/test_conversational_search_service.py index 80af4efef4c8..4426f58e4181 100644 --- a/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1beta/test_conversational_search_service.py +++ b/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1beta/test_conversational_search_service.py @@ -57,7 +57,10 @@ search_service, ) from google.cloud.discoveryengine_v1beta.types import conversation as gcd_conversation +from google.cloud.discoveryengine_v1beta.types import answer from google.cloud.discoveryengine_v1beta.types import conversation +from google.cloud.discoveryengine_v1beta.types import session +from google.cloud.discoveryengine_v1beta.types import session as gcd_session def client_cert_source_callback(): @@ -3253,6 +3256,2141 @@ async def test_list_conversations_async_pages(): assert page_.raw_page.next_page_token == token +@pytest.mark.parametrize( + "request_type", + [ + conversational_search_service.AnswerQueryRequest, + dict, + ], +) +def test_answer_query(request_type, transport: str = "grpc"): + client = ConversationalSearchServiceClient( + 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.answer_query), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = conversational_search_service.AnswerQueryResponse() + response = client.answer_query(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = conversational_search_service.AnswerQueryRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, conversational_search_service.AnswerQueryResponse) + + +def test_answer_query_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 = ConversationalSearchServiceClient( + 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.answer_query), "__call__") as call: + client.answer_query() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == conversational_search_service.AnswerQueryRequest() + + +def test_answer_query_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 = ConversationalSearchServiceClient( + 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 = conversational_search_service.AnswerQueryRequest( + serving_config="serving_config_value", + session="session_value", + user_pseudo_id="user_pseudo_id_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.answer_query), "__call__") as call: + client.answer_query(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == conversational_search_service.AnswerQueryRequest( + serving_config="serving_config_value", + session="session_value", + user_pseudo_id="user_pseudo_id_value", + ) + + +@pytest.mark.asyncio +async def test_answer_query_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 = ConversationalSearchServiceAsyncClient( + 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.answer_query), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + conversational_search_service.AnswerQueryResponse() + ) + response = await client.answer_query() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == conversational_search_service.AnswerQueryRequest() + + +@pytest.mark.asyncio +async def test_answer_query_async( + transport: str = "grpc_asyncio", + request_type=conversational_search_service.AnswerQueryRequest, +): + client = ConversationalSearchServiceAsyncClient( + 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.answer_query), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + conversational_search_service.AnswerQueryResponse() + ) + response = await client.answer_query(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = conversational_search_service.AnswerQueryRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, conversational_search_service.AnswerQueryResponse) + + +@pytest.mark.asyncio +async def test_answer_query_async_from_dict(): + await test_answer_query_async(request_type=dict) + + +def test_answer_query_field_headers(): + client = ConversationalSearchServiceClient( + 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 = conversational_search_service.AnswerQueryRequest() + + request.serving_config = "serving_config_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.answer_query), "__call__") as call: + call.return_value = conversational_search_service.AnswerQueryResponse() + client.answer_query(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", + "serving_config=serving_config_value", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_answer_query_field_headers_async(): + client = ConversationalSearchServiceAsyncClient( + 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 = conversational_search_service.AnswerQueryRequest() + + request.serving_config = "serving_config_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.answer_query), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + conversational_search_service.AnswerQueryResponse() + ) + await client.answer_query(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", + "serving_config=serving_config_value", + ) in kw["metadata"] + + +@pytest.mark.parametrize( + "request_type", + [ + conversational_search_service.GetAnswerRequest, + dict, + ], +) +def test_get_answer(request_type, transport: str = "grpc"): + client = ConversationalSearchServiceClient( + 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_answer), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = answer.Answer( + name="name_value", + state=answer.Answer.State.IN_PROGRESS, + answer_text="answer_text_value", + related_questions=["related_questions_value"], + answer_skipped_reasons=[ + answer.Answer.AnswerSkippedReason.ADVERSARIAL_QUERY_IGNORED + ], + ) + response = client.get_answer(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = conversational_search_service.GetAnswerRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, answer.Answer) + assert response.name == "name_value" + assert response.state == answer.Answer.State.IN_PROGRESS + assert response.answer_text == "answer_text_value" + assert response.related_questions == ["related_questions_value"] + assert response.answer_skipped_reasons == [ + answer.Answer.AnswerSkippedReason.ADVERSARIAL_QUERY_IGNORED + ] + + +def test_get_answer_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 = ConversationalSearchServiceClient( + 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_answer), "__call__") as call: + client.get_answer() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == conversational_search_service.GetAnswerRequest() + + +def test_get_answer_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 = ConversationalSearchServiceClient( + 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 = conversational_search_service.GetAnswerRequest( + name="name_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_answer), "__call__") as call: + client.get_answer(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == conversational_search_service.GetAnswerRequest( + name="name_value", + ) + + +@pytest.mark.asyncio +async def test_get_answer_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 = ConversationalSearchServiceAsyncClient( + 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_answer), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + answer.Answer( + name="name_value", + state=answer.Answer.State.IN_PROGRESS, + answer_text="answer_text_value", + related_questions=["related_questions_value"], + answer_skipped_reasons=[ + answer.Answer.AnswerSkippedReason.ADVERSARIAL_QUERY_IGNORED + ], + ) + ) + response = await client.get_answer() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == conversational_search_service.GetAnswerRequest() + + +@pytest.mark.asyncio +async def test_get_answer_async( + transport: str = "grpc_asyncio", + request_type=conversational_search_service.GetAnswerRequest, +): + client = ConversationalSearchServiceAsyncClient( + 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_answer), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + answer.Answer( + name="name_value", + state=answer.Answer.State.IN_PROGRESS, + answer_text="answer_text_value", + related_questions=["related_questions_value"], + answer_skipped_reasons=[ + answer.Answer.AnswerSkippedReason.ADVERSARIAL_QUERY_IGNORED + ], + ) + ) + response = await client.get_answer(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = conversational_search_service.GetAnswerRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, answer.Answer) + assert response.name == "name_value" + assert response.state == answer.Answer.State.IN_PROGRESS + assert response.answer_text == "answer_text_value" + assert response.related_questions == ["related_questions_value"] + assert response.answer_skipped_reasons == [ + answer.Answer.AnswerSkippedReason.ADVERSARIAL_QUERY_IGNORED + ] + + +@pytest.mark.asyncio +async def test_get_answer_async_from_dict(): + await test_get_answer_async(request_type=dict) + + +def test_get_answer_field_headers(): + client = ConversationalSearchServiceClient( + 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 = conversational_search_service.GetAnswerRequest() + + request.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_answer), "__call__") as call: + call.return_value = answer.Answer() + client.get_answer(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_answer_field_headers_async(): + client = ConversationalSearchServiceAsyncClient( + 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 = conversational_search_service.GetAnswerRequest() + + request.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_answer), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(answer.Answer()) + await client.get_answer(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_answer_flattened(): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_answer), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = answer.Answer() + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.get_answer( + 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_answer_flattened_error(): + client = ConversationalSearchServiceClient( + 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_answer( + conversational_search_service.GetAnswerRequest(), + name="name_value", + ) + + +@pytest.mark.asyncio +async def test_get_answer_flattened_async(): + client = ConversationalSearchServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_answer), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = answer.Answer() + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(answer.Answer()) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.get_answer( + 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_answer_flattened_error_async(): + client = ConversationalSearchServiceAsyncClient( + 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_answer( + conversational_search_service.GetAnswerRequest(), + name="name_value", + ) + + +@pytest.mark.parametrize( + "request_type", + [ + conversational_search_service.CreateSessionRequest, + dict, + ], +) +def test_create_session(request_type, transport: str = "grpc"): + client = ConversationalSearchServiceClient( + 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.create_session), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = gcd_session.Session( + name="name_value", + state=gcd_session.Session.State.IN_PROGRESS, + user_pseudo_id="user_pseudo_id_value", + ) + response = client.create_session(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = conversational_search_service.CreateSessionRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, gcd_session.Session) + assert response.name == "name_value" + assert response.state == gcd_session.Session.State.IN_PROGRESS + assert response.user_pseudo_id == "user_pseudo_id_value" + + +def test_create_session_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 = ConversationalSearchServiceClient( + 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.create_session), "__call__") as call: + client.create_session() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == conversational_search_service.CreateSessionRequest() + + +def test_create_session_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 = ConversationalSearchServiceClient( + 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 = conversational_search_service.CreateSessionRequest( + parent="parent_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.create_session), "__call__") as call: + client.create_session(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == conversational_search_service.CreateSessionRequest( + parent="parent_value", + ) + + +@pytest.mark.asyncio +async def test_create_session_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 = ConversationalSearchServiceAsyncClient( + 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.create_session), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + gcd_session.Session( + name="name_value", + state=gcd_session.Session.State.IN_PROGRESS, + user_pseudo_id="user_pseudo_id_value", + ) + ) + response = await client.create_session() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == conversational_search_service.CreateSessionRequest() + + +@pytest.mark.asyncio +async def test_create_session_async( + transport: str = "grpc_asyncio", + request_type=conversational_search_service.CreateSessionRequest, +): + client = ConversationalSearchServiceAsyncClient( + 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.create_session), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + gcd_session.Session( + name="name_value", + state=gcd_session.Session.State.IN_PROGRESS, + user_pseudo_id="user_pseudo_id_value", + ) + ) + response = await client.create_session(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = conversational_search_service.CreateSessionRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, gcd_session.Session) + assert response.name == "name_value" + assert response.state == gcd_session.Session.State.IN_PROGRESS + assert response.user_pseudo_id == "user_pseudo_id_value" + + +@pytest.mark.asyncio +async def test_create_session_async_from_dict(): + await test_create_session_async(request_type=dict) + + +def test_create_session_field_headers(): + client = ConversationalSearchServiceClient( + 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 = conversational_search_service.CreateSessionRequest() + + request.parent = "parent_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.create_session), "__call__") as call: + call.return_value = gcd_session.Session() + client.create_session(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_create_session_field_headers_async(): + client = ConversationalSearchServiceAsyncClient( + 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 = conversational_search_service.CreateSessionRequest() + + request.parent = "parent_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.create_session), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(gcd_session.Session()) + await client.create_session(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + assert args[0] == request + + # Establish that the field header was sent. + _, _, kw = call.mock_calls[0] + assert ( + "x-goog-request-params", + "parent=parent_value", + ) in kw["metadata"] + + +def test_create_session_flattened(): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.create_session), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = gcd_session.Session() + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.create_session( + parent="parent_value", + session=gcd_session.Session(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].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].session + mock_val = gcd_session.Session(name="name_value") + assert arg == mock_val + + +def test_create_session_flattened_error(): + client = ConversationalSearchServiceClient( + 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.create_session( + conversational_search_service.CreateSessionRequest(), + parent="parent_value", + session=gcd_session.Session(name="name_value"), + ) + + +@pytest.mark.asyncio +async def test_create_session_flattened_async(): + client = ConversationalSearchServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.create_session), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = gcd_session.Session() + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(gcd_session.Session()) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.create_session( + parent="parent_value", + session=gcd_session.Session(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].parent + mock_val = "parent_value" + assert arg == mock_val + arg = args[0].session + mock_val = gcd_session.Session(name="name_value") + assert arg == mock_val + + +@pytest.mark.asyncio +async def test_create_session_flattened_error_async(): + client = ConversationalSearchServiceAsyncClient( + 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.create_session( + conversational_search_service.CreateSessionRequest(), + parent="parent_value", + session=gcd_session.Session(name="name_value"), + ) + + +@pytest.mark.parametrize( + "request_type", + [ + conversational_search_service.DeleteSessionRequest, + dict, + ], +) +def test_delete_session(request_type, transport: str = "grpc"): + client = ConversationalSearchServiceClient( + 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.delete_session), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = None + response = client.delete_session(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = conversational_search_service.DeleteSessionRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert response is None + + +def test_delete_session_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 = ConversationalSearchServiceClient( + 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.delete_session), "__call__") as call: + client.delete_session() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == conversational_search_service.DeleteSessionRequest() + + +def test_delete_session_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 = ConversationalSearchServiceClient( + 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 = conversational_search_service.DeleteSessionRequest( + name="name_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.delete_session), "__call__") as call: + client.delete_session(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == conversational_search_service.DeleteSessionRequest( + name="name_value", + ) + + +@pytest.mark.asyncio +async def test_delete_session_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 = ConversationalSearchServiceAsyncClient( + 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.delete_session), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(None) + response = await client.delete_session() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == conversational_search_service.DeleteSessionRequest() + + +@pytest.mark.asyncio +async def test_delete_session_async( + transport: str = "grpc_asyncio", + request_type=conversational_search_service.DeleteSessionRequest, +): + client = ConversationalSearchServiceAsyncClient( + 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.delete_session), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(None) + response = await client.delete_session(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = conversational_search_service.DeleteSessionRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert response is None + + +@pytest.mark.asyncio +async def test_delete_session_async_from_dict(): + await test_delete_session_async(request_type=dict) + + +def test_delete_session_field_headers(): + client = ConversationalSearchServiceClient( + 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 = conversational_search_service.DeleteSessionRequest() + + request.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.delete_session), "__call__") as call: + call.return_value = None + client.delete_session(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_delete_session_field_headers_async(): + client = ConversationalSearchServiceAsyncClient( + 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 = conversational_search_service.DeleteSessionRequest() + + request.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.delete_session), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(None) + await client.delete_session(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_delete_session_flattened(): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.delete_session), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = None + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.delete_session( + 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_delete_session_flattened_error(): + client = ConversationalSearchServiceClient( + 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.delete_session( + conversational_search_service.DeleteSessionRequest(), + name="name_value", + ) + + +@pytest.mark.asyncio +async def test_delete_session_flattened_async(): + client = ConversationalSearchServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.delete_session), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = None + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(None) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.delete_session( + 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_delete_session_flattened_error_async(): + client = ConversationalSearchServiceAsyncClient( + 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.delete_session( + conversational_search_service.DeleteSessionRequest(), + name="name_value", + ) + + +@pytest.mark.parametrize( + "request_type", + [ + conversational_search_service.UpdateSessionRequest, + dict, + ], +) +def test_update_session(request_type, transport: str = "grpc"): + client = ConversationalSearchServiceClient( + 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_session), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = gcd_session.Session( + name="name_value", + state=gcd_session.Session.State.IN_PROGRESS, + user_pseudo_id="user_pseudo_id_value", + ) + response = client.update_session(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = conversational_search_service.UpdateSessionRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, gcd_session.Session) + assert response.name == "name_value" + assert response.state == gcd_session.Session.State.IN_PROGRESS + assert response.user_pseudo_id == "user_pseudo_id_value" + + +def test_update_session_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 = ConversationalSearchServiceClient( + 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_session), "__call__") as call: + client.update_session() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == conversational_search_service.UpdateSessionRequest() + + +def test_update_session_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 = ConversationalSearchServiceClient( + 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 = conversational_search_service.UpdateSessionRequest() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.update_session), "__call__") as call: + client.update_session(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == conversational_search_service.UpdateSessionRequest() + + +@pytest.mark.asyncio +async def test_update_session_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 = ConversationalSearchServiceAsyncClient( + 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_session), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + gcd_session.Session( + name="name_value", + state=gcd_session.Session.State.IN_PROGRESS, + user_pseudo_id="user_pseudo_id_value", + ) + ) + response = await client.update_session() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == conversational_search_service.UpdateSessionRequest() + + +@pytest.mark.asyncio +async def test_update_session_async( + transport: str = "grpc_asyncio", + request_type=conversational_search_service.UpdateSessionRequest, +): + client = ConversationalSearchServiceAsyncClient( + 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_session), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + gcd_session.Session( + name="name_value", + state=gcd_session.Session.State.IN_PROGRESS, + user_pseudo_id="user_pseudo_id_value", + ) + ) + response = await client.update_session(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = conversational_search_service.UpdateSessionRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, gcd_session.Session) + assert response.name == "name_value" + assert response.state == gcd_session.Session.State.IN_PROGRESS + assert response.user_pseudo_id == "user_pseudo_id_value" + + +@pytest.mark.asyncio +async def test_update_session_async_from_dict(): + await test_update_session_async(request_type=dict) + + +def test_update_session_field_headers(): + client = ConversationalSearchServiceClient( + 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 = conversational_search_service.UpdateSessionRequest() + + request.session.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.update_session), "__call__") as call: + call.return_value = gcd_session.Session() + client.update_session(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", + "session.name=name_value", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_update_session_field_headers_async(): + client = ConversationalSearchServiceAsyncClient( + 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 = conversational_search_service.UpdateSessionRequest() + + request.session.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.update_session), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(gcd_session.Session()) + await client.update_session(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", + "session.name=name_value", + ) in kw["metadata"] + + +def test_update_session_flattened(): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.update_session), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = gcd_session.Session() + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.update_session( + session=gcd_session.Session(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].session + mock_val = gcd_session.Session(name="name_value") + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val + + +def test_update_session_flattened_error(): + client = ConversationalSearchServiceClient( + 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_session( + conversational_search_service.UpdateSessionRequest(), + session=gcd_session.Session(name="name_value"), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + +@pytest.mark.asyncio +async def test_update_session_flattened_async(): + client = ConversationalSearchServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.update_session), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = gcd_session.Session() + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(gcd_session.Session()) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.update_session( + session=gcd_session.Session(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].session + mock_val = gcd_session.Session(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_session_flattened_error_async(): + client = ConversationalSearchServiceAsyncClient( + 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_session( + conversational_search_service.UpdateSessionRequest(), + session=gcd_session.Session(name="name_value"), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + +@pytest.mark.parametrize( + "request_type", + [ + conversational_search_service.GetSessionRequest, + dict, + ], +) +def test_get_session(request_type, transport: str = "grpc"): + client = ConversationalSearchServiceClient( + 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_session), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = session.Session( + name="name_value", + state=session.Session.State.IN_PROGRESS, + user_pseudo_id="user_pseudo_id_value", + ) + response = client.get_session(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = conversational_search_service.GetSessionRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, session.Session) + assert response.name == "name_value" + assert response.state == session.Session.State.IN_PROGRESS + assert response.user_pseudo_id == "user_pseudo_id_value" + + +def test_get_session_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 = ConversationalSearchServiceClient( + 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_session), "__call__") as call: + client.get_session() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == conversational_search_service.GetSessionRequest() + + +def test_get_session_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 = ConversationalSearchServiceClient( + 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 = conversational_search_service.GetSessionRequest( + name="name_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_session), "__call__") as call: + client.get_session(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == conversational_search_service.GetSessionRequest( + name="name_value", + ) + + +@pytest.mark.asyncio +async def test_get_session_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 = ConversationalSearchServiceAsyncClient( + 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_session), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + session.Session( + name="name_value", + state=session.Session.State.IN_PROGRESS, + user_pseudo_id="user_pseudo_id_value", + ) + ) + response = await client.get_session() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == conversational_search_service.GetSessionRequest() + + +@pytest.mark.asyncio +async def test_get_session_async( + transport: str = "grpc_asyncio", + request_type=conversational_search_service.GetSessionRequest, +): + client = ConversationalSearchServiceAsyncClient( + 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_session), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + session.Session( + name="name_value", + state=session.Session.State.IN_PROGRESS, + user_pseudo_id="user_pseudo_id_value", + ) + ) + response = await client.get_session(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = conversational_search_service.GetSessionRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, session.Session) + assert response.name == "name_value" + assert response.state == session.Session.State.IN_PROGRESS + assert response.user_pseudo_id == "user_pseudo_id_value" + + +@pytest.mark.asyncio +async def test_get_session_async_from_dict(): + await test_get_session_async(request_type=dict) + + +def test_get_session_field_headers(): + client = ConversationalSearchServiceClient( + 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 = conversational_search_service.GetSessionRequest() + + request.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_session), "__call__") as call: + call.return_value = session.Session() + client.get_session(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_session_field_headers_async(): + client = ConversationalSearchServiceAsyncClient( + 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 = conversational_search_service.GetSessionRequest() + + request.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_session), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(session.Session()) + await client.get_session(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_session_flattened(): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_session), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = session.Session() + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.get_session( + 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_session_flattened_error(): + client = ConversationalSearchServiceClient( + 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_session( + conversational_search_service.GetSessionRequest(), + name="name_value", + ) + + +@pytest.mark.asyncio +async def test_get_session_flattened_async(): + client = ConversationalSearchServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.get_session), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = session.Session() + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(session.Session()) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.get_session( + 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_session_flattened_error_async(): + client = ConversationalSearchServiceAsyncClient( + 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_session( + conversational_search_service.GetSessionRequest(), + name="name_value", + ) + + +@pytest.mark.parametrize( + "request_type", + [ + conversational_search_service.ListSessionsRequest, + dict, + ], +) +def test_list_sessions(request_type, transport: str = "grpc"): + client = ConversationalSearchServiceClient( + 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_sessions), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = conversational_search_service.ListSessionsResponse( + next_page_token="next_page_token_value", + ) + response = client.list_sessions(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = conversational_search_service.ListSessionsRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, pagers.ListSessionsPager) + assert response.next_page_token == "next_page_token_value" + + +def test_list_sessions_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 = ConversationalSearchServiceClient( + 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_sessions), "__call__") as call: + client.list_sessions() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == conversational_search_service.ListSessionsRequest() + + +def test_list_sessions_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 = ConversationalSearchServiceClient( + 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 = conversational_search_service.ListSessionsRequest( + parent="parent_value", + page_token="page_token_value", + filter="filter_value", + order_by="order_by_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_sessions), "__call__") as call: + client.list_sessions(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == conversational_search_service.ListSessionsRequest( + parent="parent_value", + page_token="page_token_value", + filter="filter_value", + order_by="order_by_value", + ) + + +@pytest.mark.asyncio +async def test_list_sessions_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 = ConversationalSearchServiceAsyncClient( + 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_sessions), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + conversational_search_service.ListSessionsResponse( + next_page_token="next_page_token_value", + ) + ) + response = await client.list_sessions() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == conversational_search_service.ListSessionsRequest() + + +@pytest.mark.asyncio +async def test_list_sessions_async( + transport: str = "grpc_asyncio", + request_type=conversational_search_service.ListSessionsRequest, +): + client = ConversationalSearchServiceAsyncClient( + 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_sessions), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + conversational_search_service.ListSessionsResponse( + next_page_token="next_page_token_value", + ) + ) + response = await client.list_sessions(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = conversational_search_service.ListSessionsRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, pagers.ListSessionsAsyncPager) + assert response.next_page_token == "next_page_token_value" + + +@pytest.mark.asyncio +async def test_list_sessions_async_from_dict(): + await test_list_sessions_async(request_type=dict) + + +def test_list_sessions_field_headers(): + client = ConversationalSearchServiceClient( + 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 = conversational_search_service.ListSessionsRequest() + + request.parent = "parent_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_sessions), "__call__") as call: + call.return_value = conversational_search_service.ListSessionsResponse() + client.list_sessions(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_sessions_field_headers_async(): + client = ConversationalSearchServiceAsyncClient( + 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 = conversational_search_service.ListSessionsRequest() + + request.parent = "parent_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_sessions), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + conversational_search_service.ListSessionsResponse() + ) + await client.list_sessions(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_sessions_flattened(): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_sessions), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = conversational_search_service.ListSessionsResponse() + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.list_sessions( + 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_sessions_flattened_error(): + client = ConversationalSearchServiceClient( + 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_sessions( + conversational_search_service.ListSessionsRequest(), + parent="parent_value", + ) + + +@pytest.mark.asyncio +async def test_list_sessions_flattened_async(): + client = ConversationalSearchServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_sessions), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = conversational_search_service.ListSessionsResponse() + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + conversational_search_service.ListSessionsResponse() + ) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.list_sessions( + 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_sessions_flattened_error_async(): + client = ConversationalSearchServiceAsyncClient( + 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_sessions( + conversational_search_service.ListSessionsRequest(), + parent="parent_value", + ) + + +def test_list_sessions_pager(transport_name: str = "grpc"): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport_name, + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_sessions), "__call__") as call: + # Set the response to a series of pages. + call.side_effect = ( + conversational_search_service.ListSessionsResponse( + sessions=[ + session.Session(), + session.Session(), + session.Session(), + ], + next_page_token="abc", + ), + conversational_search_service.ListSessionsResponse( + sessions=[], + next_page_token="def", + ), + conversational_search_service.ListSessionsResponse( + sessions=[ + session.Session(), + ], + next_page_token="ghi", + ), + conversational_search_service.ListSessionsResponse( + sessions=[ + session.Session(), + session.Session(), + ], + ), + RuntimeError, + ) + + metadata = () + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("parent", ""),)), + ) + pager = client.list_sessions(request={}) + + assert pager._metadata == metadata + + results = list(pager) + assert len(results) == 6 + assert all(isinstance(i, session.Session) for i in results) + + +def test_list_sessions_pages(transport_name: str = "grpc"): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport_name, + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.list_sessions), "__call__") as call: + # Set the response to a series of pages. + call.side_effect = ( + conversational_search_service.ListSessionsResponse( + sessions=[ + session.Session(), + session.Session(), + session.Session(), + ], + next_page_token="abc", + ), + conversational_search_service.ListSessionsResponse( + sessions=[], + next_page_token="def", + ), + conversational_search_service.ListSessionsResponse( + sessions=[ + session.Session(), + ], + next_page_token="ghi", + ), + conversational_search_service.ListSessionsResponse( + sessions=[ + session.Session(), + session.Session(), + ], + ), + RuntimeError, + ) + pages = list(client.list_sessions(request={}).pages) + for page_, token in zip(pages, ["abc", "def", "ghi", ""]): + assert page_.raw_page.next_page_token == token + + +@pytest.mark.asyncio +async def test_list_sessions_async_pager(): + client = ConversationalSearchServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_sessions), "__call__", new_callable=mock.AsyncMock + ) as call: + # Set the response to a series of pages. + call.side_effect = ( + conversational_search_service.ListSessionsResponse( + sessions=[ + session.Session(), + session.Session(), + session.Session(), + ], + next_page_token="abc", + ), + conversational_search_service.ListSessionsResponse( + sessions=[], + next_page_token="def", + ), + conversational_search_service.ListSessionsResponse( + sessions=[ + session.Session(), + ], + next_page_token="ghi", + ), + conversational_search_service.ListSessionsResponse( + sessions=[ + session.Session(), + session.Session(), + ], + ), + RuntimeError, + ) + async_pager = await client.list_sessions( + request={}, + ) + assert async_pager.next_page_token == "abc" + responses = [] + async for response in async_pager: # pragma: no branch + responses.append(response) + + assert len(responses) == 6 + assert all(isinstance(i, session.Session) for i in responses) + + +@pytest.mark.asyncio +async def test_list_sessions_async_pages(): + client = ConversationalSearchServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_sessions), "__call__", new_callable=mock.AsyncMock + ) as call: + # Set the response to a series of pages. + call.side_effect = ( + conversational_search_service.ListSessionsResponse( + sessions=[ + session.Session(), + session.Session(), + session.Session(), + ], + next_page_token="abc", + ), + conversational_search_service.ListSessionsResponse( + sessions=[], + next_page_token="def", + ), + conversational_search_service.ListSessionsResponse( + sessions=[ + session.Session(), + ], + next_page_token="ghi", + ), + conversational_search_service.ListSessionsResponse( + sessions=[ + session.Session(), + session.Session(), + ], + ), + RuntimeError, + ) + pages = [] + # Workaround issue in python 3.9 related to code coverage by adding `# pragma: no branch` + # See https://github.com/googleapis/gapic-generator-python/pull/1174#issuecomment-1025132372 + async for page_ in ( # pragma: no branch + await client.list_sessions(request={}) + ).pages: + pages.append(page_) + for page_, token in zip(pages, ["abc", "def", "ghi", ""]): + assert page_.raw_page.next_page_token == token + + @pytest.mark.parametrize( "request_type", [ @@ -3260,7 +5398,2038 @@ async def test_list_conversations_async_pages(): dict, ], ) -def test_converse_conversation_rest(request_type): +def test_converse_conversation_rest(request_type): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = { + "name": "projects/sample1/locations/sample2/dataStores/sample3/conversations/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 = conversational_search_service.ConverseConversationResponse( + related_questions=["related_questions_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 = conversational_search_service.ConverseConversationResponse.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.converse_conversation(request) + + # Establish that the response is the type that we expect. + assert isinstance( + response, conversational_search_service.ConverseConversationResponse + ) + assert response.related_questions == ["related_questions_value"] + + +def test_converse_conversation_rest_required_fields( + request_type=conversational_search_service.ConverseConversationRequest, +): + transport_class = transports.ConversationalSearchServiceRestTransport + + 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() + ).converse_conversation._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() + ).converse_conversation._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 = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = conversational_search_service.ConverseConversationResponse() + # 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 = ( + conversational_search_service.ConverseConversationResponse.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.converse_conversation(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_converse_conversation_rest_unset_required_fields(): + transport = transports.ConversationalSearchServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.converse_conversation._get_unset_required_fields({}) + assert set(unset_fields) == ( + set(()) + & set( + ( + "name", + "query", + ) + ) + ) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_converse_conversation_rest_interceptors(null_interceptor): + transport = transports.ConversationalSearchServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.ConversationalSearchServiceRestInterceptor(), + ) + client = ConversationalSearchServiceClient(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.ConversationalSearchServiceRestInterceptor, + "post_converse_conversation", + ) as post, mock.patch.object( + transports.ConversationalSearchServiceRestInterceptor, + "pre_converse_conversation", + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = conversational_search_service.ConverseConversationRequest.pb( + conversational_search_service.ConverseConversationRequest() + ) + 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 = ( + conversational_search_service.ConverseConversationResponse.to_json( + conversational_search_service.ConverseConversationResponse() + ) + ) + + request = conversational_search_service.ConverseConversationRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = conversational_search_service.ConverseConversationResponse() + + client.converse_conversation( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_converse_conversation_rest_bad_request( + transport: str = "rest", + request_type=conversational_search_service.ConverseConversationRequest, +): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = { + "name": "projects/sample1/locations/sample2/dataStores/sample3/conversations/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.converse_conversation(request) + + +def test_converse_conversation_rest_flattened(): + client = ConversationalSearchServiceClient( + 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 = conversational_search_service.ConverseConversationResponse() + + # get arguments that satisfy an http rule for this method + sample_request = { + "name": "projects/sample1/locations/sample2/dataStores/sample3/conversations/sample4" + } + + # get truthy value for each flattened field + mock_args = dict( + name="name_value", + query=conversation.TextInput(input="input_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 = conversational_search_service.ConverseConversationResponse.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.converse_conversation(**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/v1beta/{name=projects/*/locations/*/dataStores/*/conversations/*}:converse" + % client.transport._host, + args[1], + ) + + +def test_converse_conversation_rest_flattened_error(transport: str = "rest"): + client = ConversationalSearchServiceClient( + 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.converse_conversation( + conversational_search_service.ConverseConversationRequest(), + name="name_value", + query=conversation.TextInput(input="input_value"), + ) + + +def test_converse_conversation_rest_error(): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + +@pytest.mark.parametrize( + "request_type", + [ + conversational_search_service.CreateConversationRequest, + dict, + ], +) +def test_create_conversation_rest(request_type): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = {"parent": "projects/sample1/locations/sample2/dataStores/sample3"} + request_init["conversation"] = { + "name": "name_value", + "state": 1, + "user_pseudo_id": "user_pseudo_id_value", + "messages": [ + { + "user_input": { + "input": "input_value", + "context": { + "context_documents": [ + "context_documents_value1", + "context_documents_value2", + ], + "active_document": "active_document_value", + }, + }, + "reply": { + "reply": "reply_value", + "references": [ + { + "uri": "uri_value", + "anchor_text": "anchor_text_value", + "start": 558, + "end": 311, + } + ], + "summary": { + "summary_text": "summary_text_value", + "summary_skipped_reasons": [1], + "safety_attributes": { + "categories": ["categories_value1", "categories_value2"], + "scores": [0.656, 0.657], + }, + "summary_with_metadata": { + "summary": "summary_value", + "citation_metadata": { + "citations": [ + { + "start_index": 1189, + "end_index": 942, + "sources": [{"reference_index": 1574}], + } + ] + }, + "references": [ + { + "title": "title_value", + "document": "document_value", + "uri": "uri_value", + "chunk_contents": [ + { + "content": "content_value", + "page_identifier": "page_identifier_value", + } + ], + } + ], + }, + }, + }, + "create_time": {"seconds": 751, "nanos": 543}, + } + ], + "start_time": {}, + "end_time": {}, + } + # 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 = conversational_search_service.CreateConversationRequest.meta.fields[ + "conversation" + ] + + 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["conversation"].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["conversation"][field])): + del request_init["conversation"][field][i][subfield] + else: + del request_init["conversation"][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 = gcd_conversation.Conversation( + name="name_value", + state=gcd_conversation.Conversation.State.IN_PROGRESS, + user_pseudo_id="user_pseudo_id_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 = gcd_conversation.Conversation.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.create_conversation(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, gcd_conversation.Conversation) + assert response.name == "name_value" + assert response.state == gcd_conversation.Conversation.State.IN_PROGRESS + assert response.user_pseudo_id == "user_pseudo_id_value" + + +def test_create_conversation_rest_required_fields( + request_type=conversational_search_service.CreateConversationRequest, +): + transport_class = transports.ConversationalSearchServiceRestTransport + + 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() + ).create_conversation._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() + ).create_conversation._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 = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = gcd_conversation.Conversation() + # 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 = gcd_conversation.Conversation.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.create_conversation(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_create_conversation_rest_unset_required_fields(): + transport = transports.ConversationalSearchServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.create_conversation._get_unset_required_fields({}) + assert set(unset_fields) == ( + set(()) + & set( + ( + "parent", + "conversation", + ) + ) + ) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_create_conversation_rest_interceptors(null_interceptor): + transport = transports.ConversationalSearchServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.ConversationalSearchServiceRestInterceptor(), + ) + client = ConversationalSearchServiceClient(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.ConversationalSearchServiceRestInterceptor, + "post_create_conversation", + ) as post, mock.patch.object( + transports.ConversationalSearchServiceRestInterceptor, "pre_create_conversation" + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = conversational_search_service.CreateConversationRequest.pb( + conversational_search_service.CreateConversationRequest() + ) + 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 = gcd_conversation.Conversation.to_json( + gcd_conversation.Conversation() + ) + + request = conversational_search_service.CreateConversationRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = gcd_conversation.Conversation() + + client.create_conversation( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_create_conversation_rest_bad_request( + transport: str = "rest", + request_type=conversational_search_service.CreateConversationRequest, +): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = {"parent": "projects/sample1/locations/sample2/dataStores/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.create_conversation(request) + + +def test_create_conversation_rest_flattened(): + client = ConversationalSearchServiceClient( + 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 = gcd_conversation.Conversation() + + # get arguments that satisfy an http rule for this method + sample_request = { + "parent": "projects/sample1/locations/sample2/dataStores/sample3" + } + + # get truthy value for each flattened field + mock_args = dict( + parent="parent_value", + conversation=gcd_conversation.Conversation(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 = gcd_conversation.Conversation.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.create_conversation(**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/v1beta/{parent=projects/*/locations/*/dataStores/*}/conversations" + % client.transport._host, + args[1], + ) + + +def test_create_conversation_rest_flattened_error(transport: str = "rest"): + client = ConversationalSearchServiceClient( + 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.create_conversation( + conversational_search_service.CreateConversationRequest(), + parent="parent_value", + conversation=gcd_conversation.Conversation(name="name_value"), + ) + + +def test_create_conversation_rest_error(): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + +@pytest.mark.parametrize( + "request_type", + [ + conversational_search_service.DeleteConversationRequest, + dict, + ], +) +def test_delete_conversation_rest(request_type): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = { + "name": "projects/sample1/locations/sample2/dataStores/sample3/conversations/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 = None + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + json_return_value = "" + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + response = client.delete_conversation(request) + + # Establish that the response is the type that we expect. + assert response is None + + +def test_delete_conversation_rest_required_fields( + request_type=conversational_search_service.DeleteConversationRequest, +): + transport_class = transports.ConversationalSearchServiceRestTransport + + 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() + ).delete_conversation._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() + ).delete_conversation._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 = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = None + # 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": "delete", + "query_params": pb_request, + } + transcode.return_value = transcode_result + + response_value = Response() + response_value.status_code = 200 + json_return_value = "" + + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + response = client.delete_conversation(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_delete_conversation_rest_unset_required_fields(): + transport = transports.ConversationalSearchServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.delete_conversation._get_unset_required_fields({}) + assert set(unset_fields) == (set(()) & set(("name",))) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_delete_conversation_rest_interceptors(null_interceptor): + transport = transports.ConversationalSearchServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.ConversationalSearchServiceRestInterceptor(), + ) + client = ConversationalSearchServiceClient(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.ConversationalSearchServiceRestInterceptor, "pre_delete_conversation" + ) as pre: + pre.assert_not_called() + pb_message = conversational_search_service.DeleteConversationRequest.pb( + conversational_search_service.DeleteConversationRequest() + ) + 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() + + request = conversational_search_service.DeleteConversationRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + + client.delete_conversation( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + + +def test_delete_conversation_rest_bad_request( + transport: str = "rest", + request_type=conversational_search_service.DeleteConversationRequest, +): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = { + "name": "projects/sample1/locations/sample2/dataStores/sample3/conversations/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.delete_conversation(request) + + +def test_delete_conversation_rest_flattened(): + client = ConversationalSearchServiceClient( + 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 = None + + # get arguments that satisfy an http rule for this method + sample_request = { + "name": "projects/sample1/locations/sample2/dataStores/sample3/conversations/sample4" + } + + # 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 + json_return_value = "" + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + client.delete_conversation(**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/v1beta/{name=projects/*/locations/*/dataStores/*/conversations/*}" + % client.transport._host, + args[1], + ) + + +def test_delete_conversation_rest_flattened_error(transport: str = "rest"): + client = ConversationalSearchServiceClient( + 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.delete_conversation( + conversational_search_service.DeleteConversationRequest(), + name="name_value", + ) + + +def test_delete_conversation_rest_error(): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + +@pytest.mark.parametrize( + "request_type", + [ + conversational_search_service.UpdateConversationRequest, + dict, + ], +) +def test_update_conversation_rest(request_type): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = { + "conversation": { + "name": "projects/sample1/locations/sample2/dataStores/sample3/conversations/sample4" + } + } + request_init["conversation"] = { + "name": "projects/sample1/locations/sample2/dataStores/sample3/conversations/sample4", + "state": 1, + "user_pseudo_id": "user_pseudo_id_value", + "messages": [ + { + "user_input": { + "input": "input_value", + "context": { + "context_documents": [ + "context_documents_value1", + "context_documents_value2", + ], + "active_document": "active_document_value", + }, + }, + "reply": { + "reply": "reply_value", + "references": [ + { + "uri": "uri_value", + "anchor_text": "anchor_text_value", + "start": 558, + "end": 311, + } + ], + "summary": { + "summary_text": "summary_text_value", + "summary_skipped_reasons": [1], + "safety_attributes": { + "categories": ["categories_value1", "categories_value2"], + "scores": [0.656, 0.657], + }, + "summary_with_metadata": { + "summary": "summary_value", + "citation_metadata": { + "citations": [ + { + "start_index": 1189, + "end_index": 942, + "sources": [{"reference_index": 1574}], + } + ] + }, + "references": [ + { + "title": "title_value", + "document": "document_value", + "uri": "uri_value", + "chunk_contents": [ + { + "content": "content_value", + "page_identifier": "page_identifier_value", + } + ], + } + ], + }, + }, + }, + "create_time": {"seconds": 751, "nanos": 543}, + } + ], + "start_time": {}, + "end_time": {}, + } + # 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 = conversational_search_service.UpdateConversationRequest.meta.fields[ + "conversation" + ] + + 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["conversation"].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["conversation"][field])): + del request_init["conversation"][field][i][subfield] + else: + del request_init["conversation"][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 = gcd_conversation.Conversation( + name="name_value", + state=gcd_conversation.Conversation.State.IN_PROGRESS, + user_pseudo_id="user_pseudo_id_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 = gcd_conversation.Conversation.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_conversation(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, gcd_conversation.Conversation) + assert response.name == "name_value" + assert response.state == gcd_conversation.Conversation.State.IN_PROGRESS + assert response.user_pseudo_id == "user_pseudo_id_value" + + +def test_update_conversation_rest_required_fields( + request_type=conversational_search_service.UpdateConversationRequest, +): + transport_class = transports.ConversationalSearchServiceRestTransport + + 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_conversation._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_conversation._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 = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = gcd_conversation.Conversation() + # 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 = gcd_conversation.Conversation.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_conversation(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_update_conversation_rest_unset_required_fields(): + transport = transports.ConversationalSearchServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.update_conversation._get_unset_required_fields({}) + assert set(unset_fields) == (set(("updateMask",)) & set(("conversation",))) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_update_conversation_rest_interceptors(null_interceptor): + transport = transports.ConversationalSearchServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.ConversationalSearchServiceRestInterceptor(), + ) + client = ConversationalSearchServiceClient(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.ConversationalSearchServiceRestInterceptor, + "post_update_conversation", + ) as post, mock.patch.object( + transports.ConversationalSearchServiceRestInterceptor, "pre_update_conversation" + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = conversational_search_service.UpdateConversationRequest.pb( + conversational_search_service.UpdateConversationRequest() + ) + 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 = gcd_conversation.Conversation.to_json( + gcd_conversation.Conversation() + ) + + request = conversational_search_service.UpdateConversationRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = gcd_conversation.Conversation() + + client.update_conversation( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_update_conversation_rest_bad_request( + transport: str = "rest", + request_type=conversational_search_service.UpdateConversationRequest, +): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = { + "conversation": { + "name": "projects/sample1/locations/sample2/dataStores/sample3/conversations/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.update_conversation(request) + + +def test_update_conversation_rest_flattened(): + client = ConversationalSearchServiceClient( + 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 = gcd_conversation.Conversation() + + # get arguments that satisfy an http rule for this method + sample_request = { + "conversation": { + "name": "projects/sample1/locations/sample2/dataStores/sample3/conversations/sample4" + } + } + + # get truthy value for each flattened field + mock_args = dict( + conversation=gcd_conversation.Conversation(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 = gcd_conversation.Conversation.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_conversation(**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/v1beta/{conversation.name=projects/*/locations/*/dataStores/*/conversations/*}" + % client.transport._host, + args[1], + ) + + +def test_update_conversation_rest_flattened_error(transport: str = "rest"): + client = ConversationalSearchServiceClient( + 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_conversation( + conversational_search_service.UpdateConversationRequest(), + conversation=gcd_conversation.Conversation(name="name_value"), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + +def test_update_conversation_rest_error(): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + +@pytest.mark.parametrize( + "request_type", + [ + conversational_search_service.GetConversationRequest, + dict, + ], +) +def test_get_conversation_rest(request_type): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = { + "name": "projects/sample1/locations/sample2/dataStores/sample3/conversations/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 = conversation.Conversation( + name="name_value", + state=conversation.Conversation.State.IN_PROGRESS, + user_pseudo_id="user_pseudo_id_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 = conversation.Conversation.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_conversation(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, conversation.Conversation) + assert response.name == "name_value" + assert response.state == conversation.Conversation.State.IN_PROGRESS + assert response.user_pseudo_id == "user_pseudo_id_value" + + +def test_get_conversation_rest_required_fields( + request_type=conversational_search_service.GetConversationRequest, +): + transport_class = transports.ConversationalSearchServiceRestTransport + + 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_conversation._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_conversation._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 = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = conversation.Conversation() + # 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 = conversation.Conversation.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_conversation(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_get_conversation_rest_unset_required_fields(): + transport = transports.ConversationalSearchServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.get_conversation._get_unset_required_fields({}) + assert set(unset_fields) == (set(()) & set(("name",))) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_get_conversation_rest_interceptors(null_interceptor): + transport = transports.ConversationalSearchServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.ConversationalSearchServiceRestInterceptor(), + ) + client = ConversationalSearchServiceClient(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.ConversationalSearchServiceRestInterceptor, "post_get_conversation" + ) as post, mock.patch.object( + transports.ConversationalSearchServiceRestInterceptor, "pre_get_conversation" + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = conversational_search_service.GetConversationRequest.pb( + conversational_search_service.GetConversationRequest() + ) + 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 = conversation.Conversation.to_json( + conversation.Conversation() + ) + + request = conversational_search_service.GetConversationRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = conversation.Conversation() + + client.get_conversation( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_get_conversation_rest_bad_request( + transport: str = "rest", + request_type=conversational_search_service.GetConversationRequest, +): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = { + "name": "projects/sample1/locations/sample2/dataStores/sample3/conversations/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.get_conversation(request) + + +def test_get_conversation_rest_flattened(): + client = ConversationalSearchServiceClient( + 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 = conversation.Conversation() + + # get arguments that satisfy an http rule for this method + sample_request = { + "name": "projects/sample1/locations/sample2/dataStores/sample3/conversations/sample4" + } + + # 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 = conversation.Conversation.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_conversation(**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/v1beta/{name=projects/*/locations/*/dataStores/*/conversations/*}" + % client.transport._host, + args[1], + ) + + +def test_get_conversation_rest_flattened_error(transport: str = "rest"): + client = ConversationalSearchServiceClient( + 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_conversation( + conversational_search_service.GetConversationRequest(), + name="name_value", + ) + + +def test_get_conversation_rest_error(): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + +@pytest.mark.parametrize( + "request_type", + [ + conversational_search_service.ListConversationsRequest, + dict, + ], +) +def test_list_conversations_rest(request_type): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = {"parent": "projects/sample1/locations/sample2/dataStores/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 = conversational_search_service.ListConversationsResponse( + next_page_token="next_page_token_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 = conversational_search_service.ListConversationsResponse.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_conversations(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, pagers.ListConversationsPager) + assert response.next_page_token == "next_page_token_value" + + +def test_list_conversations_rest_required_fields( + request_type=conversational_search_service.ListConversationsRequest, +): + transport_class = transports.ConversationalSearchServiceRestTransport + + 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_conversations._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_conversations._get_unset_required_fields(jsonified_request) + # Check that path parameters and body parameters are not mixing in. + assert not set(unset_fields) - set( + ( + "filter", + "order_by", + "page_size", + "page_token", + ) + ) + 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 = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = conversational_search_service.ListConversationsResponse() + # 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 = conversational_search_service.ListConversationsResponse.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_conversations(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_list_conversations_rest_unset_required_fields(): + transport = transports.ConversationalSearchServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.list_conversations._get_unset_required_fields({}) + assert set(unset_fields) == ( + set( + ( + "filter", + "orderBy", + "pageSize", + "pageToken", + ) + ) + & set(("parent",)) + ) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_list_conversations_rest_interceptors(null_interceptor): + transport = transports.ConversationalSearchServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.ConversationalSearchServiceRestInterceptor(), + ) + client = ConversationalSearchServiceClient(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.ConversationalSearchServiceRestInterceptor, "post_list_conversations" + ) as post, mock.patch.object( + transports.ConversationalSearchServiceRestInterceptor, "pre_list_conversations" + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = conversational_search_service.ListConversationsRequest.pb( + conversational_search_service.ListConversationsRequest() + ) + 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 = ( + conversational_search_service.ListConversationsResponse.to_json( + conversational_search_service.ListConversationsResponse() + ) + ) + + request = conversational_search_service.ListConversationsRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = conversational_search_service.ListConversationsResponse() + + client.list_conversations( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_list_conversations_rest_bad_request( + transport: str = "rest", + request_type=conversational_search_service.ListConversationsRequest, +): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = {"parent": "projects/sample1/locations/sample2/dataStores/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_conversations(request) + + +def test_list_conversations_rest_flattened(): + client = ConversationalSearchServiceClient( + 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 = conversational_search_service.ListConversationsResponse() + + # get arguments that satisfy an http rule for this method + sample_request = { + "parent": "projects/sample1/locations/sample2/dataStores/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 = conversational_search_service.ListConversationsResponse.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_conversations(**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/v1beta/{parent=projects/*/locations/*/dataStores/*}/conversations" + % client.transport._host, + args[1], + ) + + +def test_list_conversations_rest_flattened_error(transport: str = "rest"): + client = ConversationalSearchServiceClient( + 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_conversations( + conversational_search_service.ListConversationsRequest(), + parent="parent_value", + ) + + +def test_list_conversations_rest_pager(transport: str = "rest"): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # TODO(kbandes): remove this mock unless there's a good reason for it. + # with mock.patch.object(path_template, 'transcode') as transcode: + # Set the response as a series of pages + response = ( + conversational_search_service.ListConversationsResponse( + conversations=[ + conversation.Conversation(), + conversation.Conversation(), + conversation.Conversation(), + ], + next_page_token="abc", + ), + conversational_search_service.ListConversationsResponse( + conversations=[], + next_page_token="def", + ), + conversational_search_service.ListConversationsResponse( + conversations=[ + conversation.Conversation(), + ], + next_page_token="ghi", + ), + conversational_search_service.ListConversationsResponse( + conversations=[ + conversation.Conversation(), + conversation.Conversation(), + ], + ), + ) + # Two responses for two calls + response = response + response + + # Wrap the values into proper Response objs + response = tuple( + conversational_search_service.ListConversationsResponse.to_json(x) + for x in response + ) + return_values = tuple(Response() for i in response) + for return_val, response_val in zip(return_values, response): + return_val._content = response_val.encode("UTF-8") + return_val.status_code = 200 + req.side_effect = return_values + + sample_request = { + "parent": "projects/sample1/locations/sample2/dataStores/sample3" + } + + pager = client.list_conversations(request=sample_request) + + results = list(pager) + assert len(results) == 6 + assert all(isinstance(i, conversation.Conversation) for i in results) + + pages = list(client.list_conversations(request=sample_request).pages) + for page_, token in zip(pages, ["abc", "def", "ghi", ""]): + assert page_.raw_page.next_page_token == token + + +@pytest.mark.parametrize( + "request_type", + [ + conversational_search_service.AnswerQueryRequest, + dict, + ], +) +def test_answer_query_rest(request_type): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", @@ -3268,44 +7437,39 @@ def test_converse_conversation_rest(request_type): # send a request that will satisfy transcoding request_init = { - "name": "projects/sample1/locations/sample2/dataStores/sample3/conversations/sample4" + "serving_config": "projects/sample1/locations/sample2/dataStores/sample3/servingConfigs/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 = conversational_search_service.ConverseConversationResponse( - related_questions=["related_questions_value"], - ) + return_value = conversational_search_service.AnswerQueryResponse() # Wrap the value into a proper Response obj response_value = Response() response_value.status_code = 200 # Convert return value to protobuf type - return_value = conversational_search_service.ConverseConversationResponse.pb( + return_value = conversational_search_service.AnswerQueryResponse.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.converse_conversation(request) + response = client.answer_query(request) # Establish that the response is the type that we expect. - assert isinstance( - response, conversational_search_service.ConverseConversationResponse - ) - assert response.related_questions == ["related_questions_value"] + assert isinstance(response, conversational_search_service.AnswerQueryResponse) -def test_converse_conversation_rest_required_fields( - request_type=conversational_search_service.ConverseConversationRequest, +def test_answer_query_rest_required_fields( + request_type=conversational_search_service.AnswerQueryRequest, ): transport_class = transports.ConversationalSearchServiceRestTransport request_init = {} - request_init["name"] = "" + request_init["serving_config"] = "" request = request_type(**request_init) pb_request = request_type.pb(request) jsonified_request = json.loads( @@ -3316,21 +7480,21 @@ def test_converse_conversation_rest_required_fields( unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).converse_conversation._get_unset_required_fields(jsonified_request) + ).answer_query._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" + jsonified_request["servingConfig"] = "serving_config_value" unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).converse_conversation._get_unset_required_fields(jsonified_request) + ).answer_query._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" + assert "servingConfig" in jsonified_request + assert jsonified_request["servingConfig"] == "serving_config_value" client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), @@ -3339,7 +7503,7 @@ def test_converse_conversation_rest_required_fields( request = request_type(**request_init) # Designate an appropriate value for the returned response. - return_value = conversational_search_service.ConverseConversationResponse() + return_value = conversational_search_service.AnswerQueryResponse() # 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 @@ -3361,34 +7525,32 @@ def test_converse_conversation_rest_required_fields( response_value.status_code = 200 # Convert return value to protobuf type - return_value = ( - conversational_search_service.ConverseConversationResponse.pb( - return_value - ) + return_value = conversational_search_service.AnswerQueryResponse.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.converse_conversation(request) + response = client.answer_query(request) expected_params = [("$alt", "json;enum-encoding=int")] actual_params = req.call_args.kwargs["params"] assert expected_params == actual_params -def test_converse_conversation_rest_unset_required_fields(): +def test_answer_query_rest_unset_required_fields(): transport = transports.ConversationalSearchServiceRestTransport( credentials=ga_credentials.AnonymousCredentials ) - unset_fields = transport.converse_conversation._get_unset_required_fields({}) + unset_fields = transport.answer_query._get_unset_required_fields({}) assert set(unset_fields) == ( set(()) & set( ( - "name", + "servingConfig", "query", ) ) @@ -3396,7 +7558,236 @@ def test_converse_conversation_rest_unset_required_fields(): @pytest.mark.parametrize("null_interceptor", [True, False]) -def test_converse_conversation_rest_interceptors(null_interceptor): +def test_answer_query_rest_interceptors(null_interceptor): + transport = transports.ConversationalSearchServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.ConversationalSearchServiceRestInterceptor(), + ) + client = ConversationalSearchServiceClient(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.ConversationalSearchServiceRestInterceptor, "post_answer_query" + ) as post, mock.patch.object( + transports.ConversationalSearchServiceRestInterceptor, "pre_answer_query" + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = conversational_search_service.AnswerQueryRequest.pb( + conversational_search_service.AnswerQueryRequest() + ) + 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 = ( + conversational_search_service.AnswerQueryResponse.to_json( + conversational_search_service.AnswerQueryResponse() + ) + ) + + request = conversational_search_service.AnswerQueryRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = conversational_search_service.AnswerQueryResponse() + + client.answer_query( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_answer_query_rest_bad_request( + transport: str = "rest", + request_type=conversational_search_service.AnswerQueryRequest, +): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = { + "serving_config": "projects/sample1/locations/sample2/dataStores/sample3/servingConfigs/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.answer_query(request) + + +def test_answer_query_rest_error(): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + +@pytest.mark.parametrize( + "request_type", + [ + conversational_search_service.GetAnswerRequest, + dict, + ], +) +def test_get_answer_rest(request_type): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = { + "name": "projects/sample1/locations/sample2/dataStores/sample3/sessions/sample4/answers/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 = answer.Answer( + name="name_value", + state=answer.Answer.State.IN_PROGRESS, + answer_text="answer_text_value", + related_questions=["related_questions_value"], + answer_skipped_reasons=[ + answer.Answer.AnswerSkippedReason.ADVERSARIAL_QUERY_IGNORED + ], + ) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = answer.Answer.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_answer(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, answer.Answer) + assert response.name == "name_value" + assert response.state == answer.Answer.State.IN_PROGRESS + assert response.answer_text == "answer_text_value" + assert response.related_questions == ["related_questions_value"] + assert response.answer_skipped_reasons == [ + answer.Answer.AnswerSkippedReason.ADVERSARIAL_QUERY_IGNORED + ] + + +def test_get_answer_rest_required_fields( + request_type=conversational_search_service.GetAnswerRequest, +): + transport_class = transports.ConversationalSearchServiceRestTransport + + 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_answer._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_answer._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 = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = answer.Answer() + # 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 = answer.Answer.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_answer(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_get_answer_rest_unset_required_fields(): + transport = transports.ConversationalSearchServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.get_answer._get_unset_required_fields({}) + assert set(unset_fields) == (set(()) & set(("name",))) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_get_answer_rest_interceptors(null_interceptor): transport = transports.ConversationalSearchServiceRestTransport( credentials=ga_credentials.AnonymousCredentials(), interceptor=None @@ -3409,16 +7800,14 @@ def test_converse_conversation_rest_interceptors(null_interceptor): ) as req, mock.patch.object( path_template, "transcode" ) as transcode, mock.patch.object( - transports.ConversationalSearchServiceRestInterceptor, - "post_converse_conversation", + transports.ConversationalSearchServiceRestInterceptor, "post_get_answer" ) as post, mock.patch.object( - transports.ConversationalSearchServiceRestInterceptor, - "pre_converse_conversation", + transports.ConversationalSearchServiceRestInterceptor, "pre_get_answer" ) as pre: pre.assert_not_called() post.assert_not_called() - pb_message = conversational_search_service.ConverseConversationRequest.pb( - conversational_search_service.ConverseConversationRequest() + pb_message = conversational_search_service.GetAnswerRequest.pb( + conversational_search_service.GetAnswerRequest() ) transcode.return_value = { "method": "post", @@ -3430,21 +7819,17 @@ def test_converse_conversation_rest_interceptors(null_interceptor): req.return_value = Response() req.return_value.status_code = 200 req.return_value.request = PreparedRequest() - req.return_value._content = ( - conversational_search_service.ConverseConversationResponse.to_json( - conversational_search_service.ConverseConversationResponse() - ) - ) + req.return_value._content = answer.Answer.to_json(answer.Answer()) - request = conversational_search_service.ConverseConversationRequest() + request = conversational_search_service.GetAnswerRequest() metadata = [ ("key", "val"), ("cephalopod", "squid"), ] pre.return_value = request, metadata - post.return_value = conversational_search_service.ConverseConversationResponse() + post.return_value = answer.Answer() - client.converse_conversation( + client.get_answer( request, metadata=[ ("key", "val"), @@ -3456,9 +7841,8 @@ def test_converse_conversation_rest_interceptors(null_interceptor): post.assert_called_once() -def test_converse_conversation_rest_bad_request( - transport: str = "rest", - request_type=conversational_search_service.ConverseConversationRequest, +def test_get_answer_rest_bad_request( + transport: str = "rest", request_type=conversational_search_service.GetAnswerRequest ): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), @@ -3467,7 +7851,7 @@ def test_converse_conversation_rest_bad_request( # send a request that will satisfy transcoding request_init = { - "name": "projects/sample1/locations/sample2/dataStores/sample3/conversations/sample4" + "name": "projects/sample1/locations/sample2/dataStores/sample3/sessions/sample4/answers/sample5" } request = request_type(**request_init) @@ -3480,10 +7864,10 @@ def test_converse_conversation_rest_bad_request( response_value.status_code = 400 response_value.request = Request() req.return_value = response_value - client.converse_conversation(request) + client.get_answer(request) -def test_converse_conversation_rest_flattened(): +def test_get_answer_rest_flattened(): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", @@ -3492,17 +7876,16 @@ def test_converse_conversation_rest_flattened(): # 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 = conversational_search_service.ConverseConversationResponse() + return_value = answer.Answer() # get arguments that satisfy an http rule for this method sample_request = { - "name": "projects/sample1/locations/sample2/dataStores/sample3/conversations/sample4" + "name": "projects/sample1/locations/sample2/dataStores/sample3/sessions/sample4/answers/sample5" } # get truthy value for each flattened field mock_args = dict( name="name_value", - query=conversation.TextInput(input="input_value"), ) mock_args.update(sample_request) @@ -3510,27 +7893,25 @@ def test_converse_conversation_rest_flattened(): response_value = Response() response_value.status_code = 200 # Convert return value to protobuf type - return_value = conversational_search_service.ConverseConversationResponse.pb( - return_value - ) + return_value = answer.Answer.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.converse_conversation(**mock_args) + client.get_answer(**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/v1beta/{name=projects/*/locations/*/dataStores/*/conversations/*}:converse" + "%s/v1beta/{name=projects/*/locations/*/dataStores/*/sessions/*/answers/*}" % client.transport._host, args[1], ) -def test_converse_conversation_rest_flattened_error(transport: str = "rest"): +def test_get_answer_rest_flattened_error(transport: str = "rest"): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, @@ -3539,14 +7920,13 @@ def test_converse_conversation_rest_flattened_error(transport: str = "rest"): # Attempting to call a method with both a request object and flattened # fields is an error. with pytest.raises(ValueError): - client.converse_conversation( - conversational_search_service.ConverseConversationRequest(), + client.get_answer( + conversational_search_service.GetAnswerRequest(), name="name_value", - query=conversation.TextInput(input="input_value"), ) -def test_converse_conversation_rest_error(): +def test_get_answer_rest_error(): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest" ) @@ -3555,11 +7935,11 @@ def test_converse_conversation_rest_error(): @pytest.mark.parametrize( "request_type", [ - conversational_search_service.CreateConversationRequest, + conversational_search_service.CreateSessionRequest, dict, ], ) -def test_create_conversation_rest(request_type): +def test_create_session_rest(request_type): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", @@ -3567,64 +7947,17 @@ def test_create_conversation_rest(request_type): # send a request that will satisfy transcoding request_init = {"parent": "projects/sample1/locations/sample2/dataStores/sample3"} - request_init["conversation"] = { + request_init["session"] = { "name": "name_value", "state": 1, "user_pseudo_id": "user_pseudo_id_value", - "messages": [ + "turns": [ { - "user_input": { - "input": "input_value", - "context": { - "context_documents": [ - "context_documents_value1", - "context_documents_value2", - ], - "active_document": "active_document_value", - }, - }, - "reply": { - "reply": "reply_value", - "references": [ - { - "uri": "uri_value", - "anchor_text": "anchor_text_value", - "start": 558, - "end": 311, - } - ], - "summary": { - "summary_text": "summary_text_value", - "summary_skipped_reasons": [1], - "safety_attributes": { - "categories": ["categories_value1", "categories_value2"], - "scores": [0.656, 0.657], - }, - "summary_with_metadata": { - "summary": "summary_value", - "citation_metadata": { - "citations": [ - { - "start_index": 1189, - "end_index": 942, - "sources": [{"reference_index": 1574}], - } - ] - }, - "references": [ - { - "title": "title_value", - "document": "document_value", - "uri": "uri_value", - } - ], - }, - }, - }, - "create_time": {"seconds": 751, "nanos": 543}, + "query": {"text": "text_value", "query_id": "query_id_value"}, + "answer": "answer_value", } ], - "start_time": {}, + "start_time": {"seconds": 751, "nanos": 543}, "end_time": {}, } # The version of a generated dependency at test runtime may differ from the version used during generation. @@ -3632,8 +7965,8 @@ def test_create_conversation_rest(request_type): # See https://github.com/googleapis/gapic-generator-python/issues/1748 # Determine if the message type is proto-plus or protobuf - test_field = conversational_search_service.CreateConversationRequest.meta.fields[ - "conversation" + test_field = conversational_search_service.CreateSessionRequest.meta.fields[ + "session" ] def get_message_fields(field): @@ -3662,7 +7995,7 @@ def get_message_fields(field): # 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["conversation"].items(): # pragma: NO COVER + for field, value in request_init["session"].items(): # pragma: NO COVER result = None is_repeated = False # For repeated fields @@ -3692,18 +8025,18 @@ def get_message_fields(field): subfield = subfield_to_delete.get("subfield") if subfield: if field_repeated: - for i in range(0, len(request_init["conversation"][field])): - del request_init["conversation"][field][i][subfield] + for i in range(0, len(request_init["session"][field])): + del request_init["session"][field][i][subfield] else: - del request_init["conversation"][field][subfield] + del request_init["session"][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 = gcd_conversation.Conversation( + return_value = gcd_session.Session( name="name_value", - state=gcd_conversation.Conversation.State.IN_PROGRESS, + state=gcd_session.Session.State.IN_PROGRESS, user_pseudo_id="user_pseudo_id_value", ) @@ -3711,22 +8044,22 @@ def get_message_fields(field): response_value = Response() response_value.status_code = 200 # Convert return value to protobuf type - return_value = gcd_conversation.Conversation.pb(return_value) + return_value = gcd_session.Session.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.create_conversation(request) + response = client.create_session(request) # Establish that the response is the type that we expect. - assert isinstance(response, gcd_conversation.Conversation) + assert isinstance(response, gcd_session.Session) assert response.name == "name_value" - assert response.state == gcd_conversation.Conversation.State.IN_PROGRESS + assert response.state == gcd_session.Session.State.IN_PROGRESS assert response.user_pseudo_id == "user_pseudo_id_value" -def test_create_conversation_rest_required_fields( - request_type=conversational_search_service.CreateConversationRequest, +def test_create_session_rest_required_fields( + request_type=conversational_search_service.CreateSessionRequest, ): transport_class = transports.ConversationalSearchServiceRestTransport @@ -3742,7 +8075,7 @@ def test_create_conversation_rest_required_fields( unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).create_conversation._get_unset_required_fields(jsonified_request) + ).create_session._get_unset_required_fields(jsonified_request) jsonified_request.update(unset_fields) # verify required fields with default values are now present @@ -3751,7 +8084,7 @@ def test_create_conversation_rest_required_fields( unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).create_conversation._get_unset_required_fields(jsonified_request) + ).create_session._get_unset_required_fields(jsonified_request) jsonified_request.update(unset_fields) # verify required fields with non-default values are left alone @@ -3765,7 +8098,7 @@ def test_create_conversation_rest_required_fields( request = request_type(**request_init) # Designate an appropriate value for the returned response. - return_value = gcd_conversation.Conversation() + return_value = gcd_session.Session() # 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 @@ -3787,38 +8120,38 @@ def test_create_conversation_rest_required_fields( response_value.status_code = 200 # Convert return value to protobuf type - return_value = gcd_conversation.Conversation.pb(return_value) + return_value = gcd_session.Session.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.create_conversation(request) + response = client.create_session(request) expected_params = [("$alt", "json;enum-encoding=int")] actual_params = req.call_args.kwargs["params"] assert expected_params == actual_params -def test_create_conversation_rest_unset_required_fields(): +def test_create_session_rest_unset_required_fields(): transport = transports.ConversationalSearchServiceRestTransport( credentials=ga_credentials.AnonymousCredentials ) - unset_fields = transport.create_conversation._get_unset_required_fields({}) + unset_fields = transport.create_session._get_unset_required_fields({}) assert set(unset_fields) == ( set(()) & set( ( "parent", - "conversation", + "session", ) ) ) @pytest.mark.parametrize("null_interceptor", [True, False]) -def test_create_conversation_rest_interceptors(null_interceptor): +def test_create_session_rest_interceptors(null_interceptor): transport = transports.ConversationalSearchServiceRestTransport( credentials=ga_credentials.AnonymousCredentials(), interceptor=None @@ -3831,15 +8164,14 @@ def test_create_conversation_rest_interceptors(null_interceptor): ) as req, mock.patch.object( path_template, "transcode" ) as transcode, mock.patch.object( - transports.ConversationalSearchServiceRestInterceptor, - "post_create_conversation", + transports.ConversationalSearchServiceRestInterceptor, "post_create_session" ) as post, mock.patch.object( - transports.ConversationalSearchServiceRestInterceptor, "pre_create_conversation" + transports.ConversationalSearchServiceRestInterceptor, "pre_create_session" ) as pre: pre.assert_not_called() post.assert_not_called() - pb_message = conversational_search_service.CreateConversationRequest.pb( - conversational_search_service.CreateConversationRequest() + pb_message = conversational_search_service.CreateSessionRequest.pb( + conversational_search_service.CreateSessionRequest() ) transcode.return_value = { "method": "post", @@ -3851,19 +8183,17 @@ def test_create_conversation_rest_interceptors(null_interceptor): req.return_value = Response() req.return_value.status_code = 200 req.return_value.request = PreparedRequest() - req.return_value._content = gcd_conversation.Conversation.to_json( - gcd_conversation.Conversation() - ) + req.return_value._content = gcd_session.Session.to_json(gcd_session.Session()) - request = conversational_search_service.CreateConversationRequest() + request = conversational_search_service.CreateSessionRequest() metadata = [ ("key", "val"), ("cephalopod", "squid"), ] pre.return_value = request, metadata - post.return_value = gcd_conversation.Conversation() + post.return_value = gcd_session.Session() - client.create_conversation( + client.create_session( request, metadata=[ ("key", "val"), @@ -3875,9 +8205,9 @@ def test_create_conversation_rest_interceptors(null_interceptor): post.assert_called_once() -def test_create_conversation_rest_bad_request( +def test_create_session_rest_bad_request( transport: str = "rest", - request_type=conversational_search_service.CreateConversationRequest, + request_type=conversational_search_service.CreateSessionRequest, ): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), @@ -3897,10 +8227,10 @@ def test_create_conversation_rest_bad_request( response_value.status_code = 400 response_value.request = Request() req.return_value = response_value - client.create_conversation(request) + client.create_session(request) -def test_create_conversation_rest_flattened(): +def test_create_session_rest_flattened(): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", @@ -3909,7 +8239,7 @@ def test_create_conversation_rest_flattened(): # 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 = gcd_conversation.Conversation() + return_value = gcd_session.Session() # get arguments that satisfy an http rule for this method sample_request = { @@ -3919,7 +8249,7 @@ def test_create_conversation_rest_flattened(): # get truthy value for each flattened field mock_args = dict( parent="parent_value", - conversation=gcd_conversation.Conversation(name="name_value"), + session=gcd_session.Session(name="name_value"), ) mock_args.update(sample_request) @@ -3927,25 +8257,25 @@ def test_create_conversation_rest_flattened(): response_value = Response() response_value.status_code = 200 # Convert return value to protobuf type - return_value = gcd_conversation.Conversation.pb(return_value) + return_value = gcd_session.Session.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.create_conversation(**mock_args) + client.create_session(**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/v1beta/{parent=projects/*/locations/*/dataStores/*}/conversations" + "%s/v1beta/{parent=projects/*/locations/*/dataStores/*}/sessions" % client.transport._host, args[1], ) -def test_create_conversation_rest_flattened_error(transport: str = "rest"): +def test_create_session_rest_flattened_error(transport: str = "rest"): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, @@ -3954,14 +8284,14 @@ def test_create_conversation_rest_flattened_error(transport: str = "rest"): # Attempting to call a method with both a request object and flattened # fields is an error. with pytest.raises(ValueError): - client.create_conversation( - conversational_search_service.CreateConversationRequest(), + client.create_session( + conversational_search_service.CreateSessionRequest(), parent="parent_value", - conversation=gcd_conversation.Conversation(name="name_value"), + session=gcd_session.Session(name="name_value"), ) -def test_create_conversation_rest_error(): +def test_create_session_rest_error(): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest" ) @@ -3970,11 +8300,11 @@ def test_create_conversation_rest_error(): @pytest.mark.parametrize( "request_type", [ - conversational_search_service.DeleteConversationRequest, + conversational_search_service.DeleteSessionRequest, dict, ], ) -def test_delete_conversation_rest(request_type): +def test_delete_session_rest(request_type): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", @@ -3982,7 +8312,7 @@ def test_delete_conversation_rest(request_type): # send a request that will satisfy transcoding request_init = { - "name": "projects/sample1/locations/sample2/dataStores/sample3/conversations/sample4" + "name": "projects/sample1/locations/sample2/dataStores/sample3/sessions/sample4" } request = request_type(**request_init) @@ -3998,14 +8328,14 @@ def test_delete_conversation_rest(request_type): response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - response = client.delete_conversation(request) + response = client.delete_session(request) # Establish that the response is the type that we expect. assert response is None -def test_delete_conversation_rest_required_fields( - request_type=conversational_search_service.DeleteConversationRequest, +def test_delete_session_rest_required_fields( + request_type=conversational_search_service.DeleteSessionRequest, ): transport_class = transports.ConversationalSearchServiceRestTransport @@ -4021,7 +8351,7 @@ def test_delete_conversation_rest_required_fields( unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).delete_conversation._get_unset_required_fields(jsonified_request) + ).delete_session._get_unset_required_fields(jsonified_request) jsonified_request.update(unset_fields) # verify required fields with default values are now present @@ -4030,7 +8360,7 @@ def test_delete_conversation_rest_required_fields( unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).delete_conversation._get_unset_required_fields(jsonified_request) + ).delete_session._get_unset_required_fields(jsonified_request) jsonified_request.update(unset_fields) # verify required fields with non-default values are left alone @@ -4068,24 +8398,24 @@ def test_delete_conversation_rest_required_fields( response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - response = client.delete_conversation(request) + response = client.delete_session(request) expected_params = [("$alt", "json;enum-encoding=int")] actual_params = req.call_args.kwargs["params"] assert expected_params == actual_params -def test_delete_conversation_rest_unset_required_fields(): +def test_delete_session_rest_unset_required_fields(): transport = transports.ConversationalSearchServiceRestTransport( credentials=ga_credentials.AnonymousCredentials ) - unset_fields = transport.delete_conversation._get_unset_required_fields({}) + unset_fields = transport.delete_session._get_unset_required_fields({}) assert set(unset_fields) == (set(()) & set(("name",))) @pytest.mark.parametrize("null_interceptor", [True, False]) -def test_delete_conversation_rest_interceptors(null_interceptor): +def test_delete_session_rest_interceptors(null_interceptor): transport = transports.ConversationalSearchServiceRestTransport( credentials=ga_credentials.AnonymousCredentials(), interceptor=None @@ -4098,11 +8428,11 @@ def test_delete_conversation_rest_interceptors(null_interceptor): ) as req, mock.patch.object( path_template, "transcode" ) as transcode, mock.patch.object( - transports.ConversationalSearchServiceRestInterceptor, "pre_delete_conversation" + transports.ConversationalSearchServiceRestInterceptor, "pre_delete_session" ) as pre: pre.assert_not_called() - pb_message = conversational_search_service.DeleteConversationRequest.pb( - conversational_search_service.DeleteConversationRequest() + pb_message = conversational_search_service.DeleteSessionRequest.pb( + conversational_search_service.DeleteSessionRequest() ) transcode.return_value = { "method": "post", @@ -4115,14 +8445,14 @@ def test_delete_conversation_rest_interceptors(null_interceptor): req.return_value.status_code = 200 req.return_value.request = PreparedRequest() - request = conversational_search_service.DeleteConversationRequest() + request = conversational_search_service.DeleteSessionRequest() metadata = [ ("key", "val"), ("cephalopod", "squid"), ] pre.return_value = request, metadata - client.delete_conversation( + client.delete_session( request, metadata=[ ("key", "val"), @@ -4133,9 +8463,9 @@ def test_delete_conversation_rest_interceptors(null_interceptor): pre.assert_called_once() -def test_delete_conversation_rest_bad_request( +def test_delete_session_rest_bad_request( transport: str = "rest", - request_type=conversational_search_service.DeleteConversationRequest, + request_type=conversational_search_service.DeleteSessionRequest, ): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), @@ -4144,7 +8474,7 @@ def test_delete_conversation_rest_bad_request( # send a request that will satisfy transcoding request_init = { - "name": "projects/sample1/locations/sample2/dataStores/sample3/conversations/sample4" + "name": "projects/sample1/locations/sample2/dataStores/sample3/sessions/sample4" } request = request_type(**request_init) @@ -4157,10 +8487,10 @@ def test_delete_conversation_rest_bad_request( response_value.status_code = 400 response_value.request = Request() req.return_value = response_value - client.delete_conversation(request) + client.delete_session(request) -def test_delete_conversation_rest_flattened(): +def test_delete_session_rest_flattened(): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", @@ -4173,7 +8503,7 @@ def test_delete_conversation_rest_flattened(): # get arguments that satisfy an http rule for this method sample_request = { - "name": "projects/sample1/locations/sample2/dataStores/sample3/conversations/sample4" + "name": "projects/sample1/locations/sample2/dataStores/sample3/sessions/sample4" } # get truthy value for each flattened field @@ -4189,117 +8519,70 @@ def test_delete_conversation_rest_flattened(): response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - client.delete_conversation(**mock_args) + client.delete_session(**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/v1beta/{name=projects/*/locations/*/dataStores/*/conversations/*}" + "%s/v1beta/{name=projects/*/locations/*/dataStores/*/sessions/*}" % client.transport._host, args[1], ) -def test_delete_conversation_rest_flattened_error(transport: str = "rest"): +def test_delete_session_rest_flattened_error(transport: str = "rest"): client = ConversationalSearchServiceClient( 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.delete_conversation( - conversational_search_service.DeleteConversationRequest(), - name="name_value", - ) - - -def test_delete_conversation_rest_error(): - client = ConversationalSearchServiceClient( - credentials=ga_credentials.AnonymousCredentials(), transport="rest" - ) - - -@pytest.mark.parametrize( - "request_type", - [ - conversational_search_service.UpdateConversationRequest, - dict, - ], -) -def test_update_conversation_rest(request_type): - client = ConversationalSearchServiceClient( - credentials=ga_credentials.AnonymousCredentials(), - transport="rest", - ) - - # send a request that will satisfy transcoding - request_init = { - "conversation": { - "name": "projects/sample1/locations/sample2/dataStores/sample3/conversations/sample4" - } - } - request_init["conversation"] = { - "name": "projects/sample1/locations/sample2/dataStores/sample3/conversations/sample4", - "state": 1, - "user_pseudo_id": "user_pseudo_id_value", - "messages": [ - { - "user_input": { - "input": "input_value", - "context": { - "context_documents": [ - "context_documents_value1", - "context_documents_value2", - ], - "active_document": "active_document_value", - }, - }, - "reply": { - "reply": "reply_value", - "references": [ - { - "uri": "uri_value", - "anchor_text": "anchor_text_value", - "start": 558, - "end": 311, - } - ], - "summary": { - "summary_text": "summary_text_value", - "summary_skipped_reasons": [1], - "safety_attributes": { - "categories": ["categories_value1", "categories_value2"], - "scores": [0.656, 0.657], - }, - "summary_with_metadata": { - "summary": "summary_value", - "citation_metadata": { - "citations": [ - { - "start_index": 1189, - "end_index": 942, - "sources": [{"reference_index": 1574}], - } - ] - }, - "references": [ - { - "title": "title_value", - "document": "document_value", - "uri": "uri_value", - } - ], - }, - }, - }, - "create_time": {"seconds": 751, "nanos": 543}, + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + client.delete_session( + conversational_search_service.DeleteSessionRequest(), + name="name_value", + ) + + +def test_delete_session_rest_error(): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + +@pytest.mark.parametrize( + "request_type", + [ + conversational_search_service.UpdateSessionRequest, + dict, + ], +) +def test_update_session_rest(request_type): + client = ConversationalSearchServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = { + "session": { + "name": "projects/sample1/locations/sample2/dataStores/sample3/sessions/sample4" + } + } + request_init["session"] = { + "name": "projects/sample1/locations/sample2/dataStores/sample3/sessions/sample4", + "state": 1, + "user_pseudo_id": "user_pseudo_id_value", + "turns": [ + { + "query": {"text": "text_value", "query_id": "query_id_value"}, + "answer": "answer_value", } ], - "start_time": {}, + "start_time": {"seconds": 751, "nanos": 543}, "end_time": {}, } # The version of a generated dependency at test runtime may differ from the version used during generation. @@ -4307,8 +8590,8 @@ def test_update_conversation_rest(request_type): # See https://github.com/googleapis/gapic-generator-python/issues/1748 # Determine if the message type is proto-plus or protobuf - test_field = conversational_search_service.UpdateConversationRequest.meta.fields[ - "conversation" + test_field = conversational_search_service.UpdateSessionRequest.meta.fields[ + "session" ] def get_message_fields(field): @@ -4337,7 +8620,7 @@ def get_message_fields(field): # 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["conversation"].items(): # pragma: NO COVER + for field, value in request_init["session"].items(): # pragma: NO COVER result = None is_repeated = False # For repeated fields @@ -4367,18 +8650,18 @@ def get_message_fields(field): subfield = subfield_to_delete.get("subfield") if subfield: if field_repeated: - for i in range(0, len(request_init["conversation"][field])): - del request_init["conversation"][field][i][subfield] + for i in range(0, len(request_init["session"][field])): + del request_init["session"][field][i][subfield] else: - del request_init["conversation"][field][subfield] + del request_init["session"][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 = gcd_conversation.Conversation( + return_value = gcd_session.Session( name="name_value", - state=gcd_conversation.Conversation.State.IN_PROGRESS, + state=gcd_session.Session.State.IN_PROGRESS, user_pseudo_id="user_pseudo_id_value", ) @@ -4386,22 +8669,22 @@ def get_message_fields(field): response_value = Response() response_value.status_code = 200 # Convert return value to protobuf type - return_value = gcd_conversation.Conversation.pb(return_value) + return_value = gcd_session.Session.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_conversation(request) + response = client.update_session(request) # Establish that the response is the type that we expect. - assert isinstance(response, gcd_conversation.Conversation) + assert isinstance(response, gcd_session.Session) assert response.name == "name_value" - assert response.state == gcd_conversation.Conversation.State.IN_PROGRESS + assert response.state == gcd_session.Session.State.IN_PROGRESS assert response.user_pseudo_id == "user_pseudo_id_value" -def test_update_conversation_rest_required_fields( - request_type=conversational_search_service.UpdateConversationRequest, +def test_update_session_rest_required_fields( + request_type=conversational_search_service.UpdateSessionRequest, ): transport_class = transports.ConversationalSearchServiceRestTransport @@ -4416,14 +8699,14 @@ def test_update_conversation_rest_required_fields( unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).update_conversation._get_unset_required_fields(jsonified_request) + ).update_session._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_conversation._get_unset_required_fields(jsonified_request) + ).update_session._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) @@ -4437,7 +8720,7 @@ def test_update_conversation_rest_required_fields( request = request_type(**request_init) # Designate an appropriate value for the returned response. - return_value = gcd_conversation.Conversation() + return_value = gcd_session.Session() # 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 @@ -4459,30 +8742,30 @@ def test_update_conversation_rest_required_fields( response_value.status_code = 200 # Convert return value to protobuf type - return_value = gcd_conversation.Conversation.pb(return_value) + return_value = gcd_session.Session.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_conversation(request) + response = client.update_session(request) expected_params = [("$alt", "json;enum-encoding=int")] actual_params = req.call_args.kwargs["params"] assert expected_params == actual_params -def test_update_conversation_rest_unset_required_fields(): +def test_update_session_rest_unset_required_fields(): transport = transports.ConversationalSearchServiceRestTransport( credentials=ga_credentials.AnonymousCredentials ) - unset_fields = transport.update_conversation._get_unset_required_fields({}) - assert set(unset_fields) == (set(("updateMask",)) & set(("conversation",))) + unset_fields = transport.update_session._get_unset_required_fields({}) + assert set(unset_fields) == (set(("updateMask",)) & set(("session",))) @pytest.mark.parametrize("null_interceptor", [True, False]) -def test_update_conversation_rest_interceptors(null_interceptor): +def test_update_session_rest_interceptors(null_interceptor): transport = transports.ConversationalSearchServiceRestTransport( credentials=ga_credentials.AnonymousCredentials(), interceptor=None @@ -4495,15 +8778,14 @@ def test_update_conversation_rest_interceptors(null_interceptor): ) as req, mock.patch.object( path_template, "transcode" ) as transcode, mock.patch.object( - transports.ConversationalSearchServiceRestInterceptor, - "post_update_conversation", + transports.ConversationalSearchServiceRestInterceptor, "post_update_session" ) as post, mock.patch.object( - transports.ConversationalSearchServiceRestInterceptor, "pre_update_conversation" + transports.ConversationalSearchServiceRestInterceptor, "pre_update_session" ) as pre: pre.assert_not_called() post.assert_not_called() - pb_message = conversational_search_service.UpdateConversationRequest.pb( - conversational_search_service.UpdateConversationRequest() + pb_message = conversational_search_service.UpdateSessionRequest.pb( + conversational_search_service.UpdateSessionRequest() ) transcode.return_value = { "method": "post", @@ -4515,19 +8797,17 @@ def test_update_conversation_rest_interceptors(null_interceptor): req.return_value = Response() req.return_value.status_code = 200 req.return_value.request = PreparedRequest() - req.return_value._content = gcd_conversation.Conversation.to_json( - gcd_conversation.Conversation() - ) + req.return_value._content = gcd_session.Session.to_json(gcd_session.Session()) - request = conversational_search_service.UpdateConversationRequest() + request = conversational_search_service.UpdateSessionRequest() metadata = [ ("key", "val"), ("cephalopod", "squid"), ] pre.return_value = request, metadata - post.return_value = gcd_conversation.Conversation() + post.return_value = gcd_session.Session() - client.update_conversation( + client.update_session( request, metadata=[ ("key", "val"), @@ -4539,9 +8819,9 @@ def test_update_conversation_rest_interceptors(null_interceptor): post.assert_called_once() -def test_update_conversation_rest_bad_request( +def test_update_session_rest_bad_request( transport: str = "rest", - request_type=conversational_search_service.UpdateConversationRequest, + request_type=conversational_search_service.UpdateSessionRequest, ): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), @@ -4550,8 +8830,8 @@ def test_update_conversation_rest_bad_request( # send a request that will satisfy transcoding request_init = { - "conversation": { - "name": "projects/sample1/locations/sample2/dataStores/sample3/conversations/sample4" + "session": { + "name": "projects/sample1/locations/sample2/dataStores/sample3/sessions/sample4" } } request = request_type(**request_init) @@ -4565,10 +8845,10 @@ def test_update_conversation_rest_bad_request( response_value.status_code = 400 response_value.request = Request() req.return_value = response_value - client.update_conversation(request) + client.update_session(request) -def test_update_conversation_rest_flattened(): +def test_update_session_rest_flattened(): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", @@ -4577,18 +8857,18 @@ def test_update_conversation_rest_flattened(): # 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 = gcd_conversation.Conversation() + return_value = gcd_session.Session() # get arguments that satisfy an http rule for this method sample_request = { - "conversation": { - "name": "projects/sample1/locations/sample2/dataStores/sample3/conversations/sample4" + "session": { + "name": "projects/sample1/locations/sample2/dataStores/sample3/sessions/sample4" } } # get truthy value for each flattened field mock_args = dict( - conversation=gcd_conversation.Conversation(name="name_value"), + session=gcd_session.Session(name="name_value"), update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), ) mock_args.update(sample_request) @@ -4597,25 +8877,25 @@ def test_update_conversation_rest_flattened(): response_value = Response() response_value.status_code = 200 # Convert return value to protobuf type - return_value = gcd_conversation.Conversation.pb(return_value) + return_value = gcd_session.Session.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_conversation(**mock_args) + client.update_session(**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/v1beta/{conversation.name=projects/*/locations/*/dataStores/*/conversations/*}" + "%s/v1beta/{session.name=projects/*/locations/*/dataStores/*/sessions/*}" % client.transport._host, args[1], ) -def test_update_conversation_rest_flattened_error(transport: str = "rest"): +def test_update_session_rest_flattened_error(transport: str = "rest"): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, @@ -4624,14 +8904,14 @@ def test_update_conversation_rest_flattened_error(transport: str = "rest"): # Attempting to call a method with both a request object and flattened # fields is an error. with pytest.raises(ValueError): - client.update_conversation( - conversational_search_service.UpdateConversationRequest(), - conversation=gcd_conversation.Conversation(name="name_value"), + client.update_session( + conversational_search_service.UpdateSessionRequest(), + session=gcd_session.Session(name="name_value"), update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), ) -def test_update_conversation_rest_error(): +def test_update_session_rest_error(): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest" ) @@ -4640,11 +8920,11 @@ def test_update_conversation_rest_error(): @pytest.mark.parametrize( "request_type", [ - conversational_search_service.GetConversationRequest, + conversational_search_service.GetSessionRequest, dict, ], ) -def test_get_conversation_rest(request_type): +def test_get_session_rest(request_type): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", @@ -4652,16 +8932,16 @@ def test_get_conversation_rest(request_type): # send a request that will satisfy transcoding request_init = { - "name": "projects/sample1/locations/sample2/dataStores/sample3/conversations/sample4" + "name": "projects/sample1/locations/sample2/dataStores/sample3/sessions/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 = conversation.Conversation( + return_value = session.Session( name="name_value", - state=conversation.Conversation.State.IN_PROGRESS, + state=session.Session.State.IN_PROGRESS, user_pseudo_id="user_pseudo_id_value", ) @@ -4669,22 +8949,22 @@ def test_get_conversation_rest(request_type): response_value = Response() response_value.status_code = 200 # Convert return value to protobuf type - return_value = conversation.Conversation.pb(return_value) + return_value = session.Session.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_conversation(request) + response = client.get_session(request) # Establish that the response is the type that we expect. - assert isinstance(response, conversation.Conversation) + assert isinstance(response, session.Session) assert response.name == "name_value" - assert response.state == conversation.Conversation.State.IN_PROGRESS + assert response.state == session.Session.State.IN_PROGRESS assert response.user_pseudo_id == "user_pseudo_id_value" -def test_get_conversation_rest_required_fields( - request_type=conversational_search_service.GetConversationRequest, +def test_get_session_rest_required_fields( + request_type=conversational_search_service.GetSessionRequest, ): transport_class = transports.ConversationalSearchServiceRestTransport @@ -4700,7 +8980,7 @@ def test_get_conversation_rest_required_fields( unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).get_conversation._get_unset_required_fields(jsonified_request) + ).get_session._get_unset_required_fields(jsonified_request) jsonified_request.update(unset_fields) # verify required fields with default values are now present @@ -4709,7 +8989,7 @@ def test_get_conversation_rest_required_fields( unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).get_conversation._get_unset_required_fields(jsonified_request) + ).get_session._get_unset_required_fields(jsonified_request) jsonified_request.update(unset_fields) # verify required fields with non-default values are left alone @@ -4723,7 +9003,7 @@ def test_get_conversation_rest_required_fields( request = request_type(**request_init) # Designate an appropriate value for the returned response. - return_value = conversation.Conversation() + return_value = session.Session() # 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 @@ -4744,30 +9024,30 @@ def test_get_conversation_rest_required_fields( response_value.status_code = 200 # Convert return value to protobuf type - return_value = conversation.Conversation.pb(return_value) + return_value = session.Session.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_conversation(request) + response = client.get_session(request) expected_params = [("$alt", "json;enum-encoding=int")] actual_params = req.call_args.kwargs["params"] assert expected_params == actual_params -def test_get_conversation_rest_unset_required_fields(): +def test_get_session_rest_unset_required_fields(): transport = transports.ConversationalSearchServiceRestTransport( credentials=ga_credentials.AnonymousCredentials ) - unset_fields = transport.get_conversation._get_unset_required_fields({}) + unset_fields = transport.get_session._get_unset_required_fields({}) assert set(unset_fields) == (set(()) & set(("name",))) @pytest.mark.parametrize("null_interceptor", [True, False]) -def test_get_conversation_rest_interceptors(null_interceptor): +def test_get_session_rest_interceptors(null_interceptor): transport = transports.ConversationalSearchServiceRestTransport( credentials=ga_credentials.AnonymousCredentials(), interceptor=None @@ -4780,14 +9060,14 @@ def test_get_conversation_rest_interceptors(null_interceptor): ) as req, mock.patch.object( path_template, "transcode" ) as transcode, mock.patch.object( - transports.ConversationalSearchServiceRestInterceptor, "post_get_conversation" + transports.ConversationalSearchServiceRestInterceptor, "post_get_session" ) as post, mock.patch.object( - transports.ConversationalSearchServiceRestInterceptor, "pre_get_conversation" + transports.ConversationalSearchServiceRestInterceptor, "pre_get_session" ) as pre: pre.assert_not_called() post.assert_not_called() - pb_message = conversational_search_service.GetConversationRequest.pb( - conversational_search_service.GetConversationRequest() + pb_message = conversational_search_service.GetSessionRequest.pb( + conversational_search_service.GetSessionRequest() ) transcode.return_value = { "method": "post", @@ -4799,19 +9079,17 @@ def test_get_conversation_rest_interceptors(null_interceptor): req.return_value = Response() req.return_value.status_code = 200 req.return_value.request = PreparedRequest() - req.return_value._content = conversation.Conversation.to_json( - conversation.Conversation() - ) + req.return_value._content = session.Session.to_json(session.Session()) - request = conversational_search_service.GetConversationRequest() + request = conversational_search_service.GetSessionRequest() metadata = [ ("key", "val"), ("cephalopod", "squid"), ] pre.return_value = request, metadata - post.return_value = conversation.Conversation() + post.return_value = session.Session() - client.get_conversation( + client.get_session( request, metadata=[ ("key", "val"), @@ -4823,9 +9101,9 @@ def test_get_conversation_rest_interceptors(null_interceptor): post.assert_called_once() -def test_get_conversation_rest_bad_request( +def test_get_session_rest_bad_request( transport: str = "rest", - request_type=conversational_search_service.GetConversationRequest, + request_type=conversational_search_service.GetSessionRequest, ): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), @@ -4834,7 +9112,7 @@ def test_get_conversation_rest_bad_request( # send a request that will satisfy transcoding request_init = { - "name": "projects/sample1/locations/sample2/dataStores/sample3/conversations/sample4" + "name": "projects/sample1/locations/sample2/dataStores/sample3/sessions/sample4" } request = request_type(**request_init) @@ -4847,10 +9125,10 @@ def test_get_conversation_rest_bad_request( response_value.status_code = 400 response_value.request = Request() req.return_value = response_value - client.get_conversation(request) + client.get_session(request) -def test_get_conversation_rest_flattened(): +def test_get_session_rest_flattened(): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", @@ -4859,11 +9137,11 @@ def test_get_conversation_rest_flattened(): # 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 = conversation.Conversation() + return_value = session.Session() # get arguments that satisfy an http rule for this method sample_request = { - "name": "projects/sample1/locations/sample2/dataStores/sample3/conversations/sample4" + "name": "projects/sample1/locations/sample2/dataStores/sample3/sessions/sample4" } # get truthy value for each flattened field @@ -4876,25 +9154,25 @@ def test_get_conversation_rest_flattened(): response_value = Response() response_value.status_code = 200 # Convert return value to protobuf type - return_value = conversation.Conversation.pb(return_value) + return_value = session.Session.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_conversation(**mock_args) + client.get_session(**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/v1beta/{name=projects/*/locations/*/dataStores/*/conversations/*}" + "%s/v1beta/{name=projects/*/locations/*/dataStores/*/sessions/*}" % client.transport._host, args[1], ) -def test_get_conversation_rest_flattened_error(transport: str = "rest"): +def test_get_session_rest_flattened_error(transport: str = "rest"): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, @@ -4903,13 +9181,13 @@ def test_get_conversation_rest_flattened_error(transport: str = "rest"): # Attempting to call a method with both a request object and flattened # fields is an error. with pytest.raises(ValueError): - client.get_conversation( - conversational_search_service.GetConversationRequest(), + client.get_session( + conversational_search_service.GetSessionRequest(), name="name_value", ) -def test_get_conversation_rest_error(): +def test_get_session_rest_error(): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest" ) @@ -4918,11 +9196,11 @@ def test_get_conversation_rest_error(): @pytest.mark.parametrize( "request_type", [ - conversational_search_service.ListConversationsRequest, + conversational_search_service.ListSessionsRequest, dict, ], ) -def test_list_conversations_rest(request_type): +def test_list_sessions_rest(request_type): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", @@ -4935,7 +9213,7 @@ def test_list_conversations_rest(request_type): # 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 = conversational_search_service.ListConversationsResponse( + return_value = conversational_search_service.ListSessionsResponse( next_page_token="next_page_token_value", ) @@ -4943,22 +9221,22 @@ def test_list_conversations_rest(request_type): response_value = Response() response_value.status_code = 200 # Convert return value to protobuf type - return_value = conversational_search_service.ListConversationsResponse.pb( + return_value = conversational_search_service.ListSessionsResponse.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_conversations(request) + response = client.list_sessions(request) # Establish that the response is the type that we expect. - assert isinstance(response, pagers.ListConversationsPager) + assert isinstance(response, pagers.ListSessionsPager) assert response.next_page_token == "next_page_token_value" -def test_list_conversations_rest_required_fields( - request_type=conversational_search_service.ListConversationsRequest, +def test_list_sessions_rest_required_fields( + request_type=conversational_search_service.ListSessionsRequest, ): transport_class = transports.ConversationalSearchServiceRestTransport @@ -4974,7 +9252,7 @@ def test_list_conversations_rest_required_fields( unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).list_conversations._get_unset_required_fields(jsonified_request) + ).list_sessions._get_unset_required_fields(jsonified_request) jsonified_request.update(unset_fields) # verify required fields with default values are now present @@ -4983,7 +9261,7 @@ def test_list_conversations_rest_required_fields( unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).list_conversations._get_unset_required_fields(jsonified_request) + ).list_sessions._get_unset_required_fields(jsonified_request) # Check that path parameters and body parameters are not mixing in. assert not set(unset_fields) - set( ( @@ -5006,7 +9284,7 @@ def test_list_conversations_rest_required_fields( request = request_type(**request_init) # Designate an appropriate value for the returned response. - return_value = conversational_search_service.ListConversationsResponse() + return_value = conversational_search_service.ListSessionsResponse() # 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 @@ -5027,7 +9305,7 @@ def test_list_conversations_rest_required_fields( response_value.status_code = 200 # Convert return value to protobuf type - return_value = conversational_search_service.ListConversationsResponse.pb( + return_value = conversational_search_service.ListSessionsResponse.pb( return_value ) json_return_value = json_format.MessageToJson(return_value) @@ -5035,19 +9313,19 @@ def test_list_conversations_rest_required_fields( response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - response = client.list_conversations(request) + response = client.list_sessions(request) expected_params = [("$alt", "json;enum-encoding=int")] actual_params = req.call_args.kwargs["params"] assert expected_params == actual_params -def test_list_conversations_rest_unset_required_fields(): +def test_list_sessions_rest_unset_required_fields(): transport = transports.ConversationalSearchServiceRestTransport( credentials=ga_credentials.AnonymousCredentials ) - unset_fields = transport.list_conversations._get_unset_required_fields({}) + unset_fields = transport.list_sessions._get_unset_required_fields({}) assert set(unset_fields) == ( set( ( @@ -5062,7 +9340,7 @@ def test_list_conversations_rest_unset_required_fields(): @pytest.mark.parametrize("null_interceptor", [True, False]) -def test_list_conversations_rest_interceptors(null_interceptor): +def test_list_sessions_rest_interceptors(null_interceptor): transport = transports.ConversationalSearchServiceRestTransport( credentials=ga_credentials.AnonymousCredentials(), interceptor=None @@ -5075,14 +9353,14 @@ def test_list_conversations_rest_interceptors(null_interceptor): ) as req, mock.patch.object( path_template, "transcode" ) as transcode, mock.patch.object( - transports.ConversationalSearchServiceRestInterceptor, "post_list_conversations" + transports.ConversationalSearchServiceRestInterceptor, "post_list_sessions" ) as post, mock.patch.object( - transports.ConversationalSearchServiceRestInterceptor, "pre_list_conversations" + transports.ConversationalSearchServiceRestInterceptor, "pre_list_sessions" ) as pre: pre.assert_not_called() post.assert_not_called() - pb_message = conversational_search_service.ListConversationsRequest.pb( - conversational_search_service.ListConversationsRequest() + pb_message = conversational_search_service.ListSessionsRequest.pb( + conversational_search_service.ListSessionsRequest() ) transcode.return_value = { "method": "post", @@ -5095,20 +9373,20 @@ def test_list_conversations_rest_interceptors(null_interceptor): req.return_value.status_code = 200 req.return_value.request = PreparedRequest() req.return_value._content = ( - conversational_search_service.ListConversationsResponse.to_json( - conversational_search_service.ListConversationsResponse() + conversational_search_service.ListSessionsResponse.to_json( + conversational_search_service.ListSessionsResponse() ) ) - request = conversational_search_service.ListConversationsRequest() + request = conversational_search_service.ListSessionsRequest() metadata = [ ("key", "val"), ("cephalopod", "squid"), ] pre.return_value = request, metadata - post.return_value = conversational_search_service.ListConversationsResponse() + post.return_value = conversational_search_service.ListSessionsResponse() - client.list_conversations( + client.list_sessions( request, metadata=[ ("key", "val"), @@ -5120,9 +9398,9 @@ def test_list_conversations_rest_interceptors(null_interceptor): post.assert_called_once() -def test_list_conversations_rest_bad_request( +def test_list_sessions_rest_bad_request( transport: str = "rest", - request_type=conversational_search_service.ListConversationsRequest, + request_type=conversational_search_service.ListSessionsRequest, ): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), @@ -5142,10 +9420,10 @@ def test_list_conversations_rest_bad_request( response_value.status_code = 400 response_value.request = Request() req.return_value = response_value - client.list_conversations(request) + client.list_sessions(request) -def test_list_conversations_rest_flattened(): +def test_list_sessions_rest_flattened(): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", @@ -5154,7 +9432,7 @@ def test_list_conversations_rest_flattened(): # 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 = conversational_search_service.ListConversationsResponse() + return_value = conversational_search_service.ListSessionsResponse() # get arguments that satisfy an http rule for this method sample_request = { @@ -5171,27 +9449,27 @@ def test_list_conversations_rest_flattened(): response_value = Response() response_value.status_code = 200 # Convert return value to protobuf type - return_value = conversational_search_service.ListConversationsResponse.pb( + return_value = conversational_search_service.ListSessionsResponse.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_conversations(**mock_args) + client.list_sessions(**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/v1beta/{parent=projects/*/locations/*/dataStores/*}/conversations" + "%s/v1beta/{parent=projects/*/locations/*/dataStores/*}/sessions" % client.transport._host, args[1], ) -def test_list_conversations_rest_flattened_error(transport: str = "rest"): +def test_list_sessions_rest_flattened_error(transport: str = "rest"): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, @@ -5200,13 +9478,13 @@ def test_list_conversations_rest_flattened_error(transport: str = "rest"): # Attempting to call a method with both a request object and flattened # fields is an error. with pytest.raises(ValueError): - client.list_conversations( - conversational_search_service.ListConversationsRequest(), + client.list_sessions( + conversational_search_service.ListSessionsRequest(), parent="parent_value", ) -def test_list_conversations_rest_pager(transport: str = "rest"): +def test_list_sessions_rest_pager(transport: str = "rest"): client = ConversationalSearchServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, @@ -5218,28 +9496,28 @@ def test_list_conversations_rest_pager(transport: str = "rest"): # with mock.patch.object(path_template, 'transcode') as transcode: # Set the response as a series of pages response = ( - conversational_search_service.ListConversationsResponse( - conversations=[ - conversation.Conversation(), - conversation.Conversation(), - conversation.Conversation(), + conversational_search_service.ListSessionsResponse( + sessions=[ + session.Session(), + session.Session(), + session.Session(), ], next_page_token="abc", ), - conversational_search_service.ListConversationsResponse( - conversations=[], + conversational_search_service.ListSessionsResponse( + sessions=[], next_page_token="def", ), - conversational_search_service.ListConversationsResponse( - conversations=[ - conversation.Conversation(), + conversational_search_service.ListSessionsResponse( + sessions=[ + session.Session(), ], next_page_token="ghi", ), - conversational_search_service.ListConversationsResponse( - conversations=[ - conversation.Conversation(), - conversation.Conversation(), + conversational_search_service.ListSessionsResponse( + sessions=[ + session.Session(), + session.Session(), ], ), ) @@ -5248,7 +9526,7 @@ def test_list_conversations_rest_pager(transport: str = "rest"): # Wrap the values into proper Response objs response = tuple( - conversational_search_service.ListConversationsResponse.to_json(x) + conversational_search_service.ListSessionsResponse.to_json(x) for x in response ) return_values = tuple(Response() for i in response) @@ -5261,13 +9539,13 @@ def test_list_conversations_rest_pager(transport: str = "rest"): "parent": "projects/sample1/locations/sample2/dataStores/sample3" } - pager = client.list_conversations(request=sample_request) + pager = client.list_sessions(request=sample_request) results = list(pager) assert len(results) == 6 - assert all(isinstance(i, conversation.Conversation) for i in results) + assert all(isinstance(i, session.Session) for i in results) - pages = list(client.list_conversations(request=sample_request).pages) + pages = list(client.list_sessions(request=sample_request).pages) for page_, token in zip(pages, ["abc", "def", "ghi", ""]): assert page_.raw_page.next_page_token == token @@ -5417,6 +9695,13 @@ def test_conversational_search_service_base_transport(): "update_conversation", "get_conversation", "list_conversations", + "answer_query", + "get_answer", + "create_session", + "delete_session", + "update_session", + "get_session", + "list_sessions", "get_operation", "list_operations", ) @@ -5704,6 +9989,27 @@ def test_conversational_search_service_client_transport_session_collision( session1 = client1.transport.list_conversations._session session2 = client2.transport.list_conversations._session assert session1 != session2 + session1 = client1.transport.answer_query._session + session2 = client2.transport.answer_query._session + assert session1 != session2 + session1 = client1.transport.get_answer._session + session2 = client2.transport.get_answer._session + assert session1 != session2 + session1 = client1.transport.create_session._session + session2 = client2.transport.create_session._session + assert session1 != session2 + session1 = client1.transport.delete_session._session + session2 = client2.transport.delete_session._session + assert session1 != session2 + session1 = client1.transport.update_session._session + session2 = client2.transport.update_session._session + assert session1 != session2 + session1 = client1.transport.get_session._session + session2 = client2.transport.get_session._session + assert session1 != session2 + session1 = client1.transport.list_sessions._session + session2 = client2.transport.list_sessions._session + assert session1 != session2 def test_conversational_search_service_grpc_transport_channel(): @@ -5832,11 +10138,82 @@ def test_conversational_search_service_transport_channel_mtls_with_adc(transport assert transport.grpc_channel == mock_grpc_channel -def test_conversation_path(): +def test_answer_path(): project = "squid" location = "clam" data_store = "whelk" - conversation = "octopus" + session = "octopus" + answer = "oyster" + expected = "projects/{project}/locations/{location}/dataStores/{data_store}/sessions/{session}/answers/{answer}".format( + project=project, + location=location, + data_store=data_store, + session=session, + answer=answer, + ) + actual = ConversationalSearchServiceClient.answer_path( + project, location, data_store, session, answer + ) + assert expected == actual + + +def test_parse_answer_path(): + expected = { + "project": "nudibranch", + "location": "cuttlefish", + "data_store": "mussel", + "session": "winkle", + "answer": "nautilus", + } + path = ConversationalSearchServiceClient.answer_path(**expected) + + # Check that the path construction is reversible. + actual = ConversationalSearchServiceClient.parse_answer_path(path) + assert expected == actual + + +def test_chunk_path(): + project = "scallop" + location = "abalone" + data_store = "squid" + branch = "clam" + document = "whelk" + chunk = "octopus" + expected = "projects/{project}/locations/{location}/dataStores/{data_store}/branches/{branch}/documents/{document}/chunks/{chunk}".format( + project=project, + location=location, + data_store=data_store, + branch=branch, + document=document, + chunk=chunk, + ) + actual = ConversationalSearchServiceClient.chunk_path( + project, location, data_store, branch, document, chunk + ) + assert expected == actual + + +def test_parse_chunk_path(): + expected = { + "project": "oyster", + "location": "nudibranch", + "data_store": "cuttlefish", + "branch": "mussel", + "document": "winkle", + "chunk": "nautilus", + } + path = ConversationalSearchServiceClient.chunk_path(**expected) + + # Check that the path construction is reversible. + actual = ConversationalSearchServiceClient.parse_chunk_path(path) + assert expected == actual + + +def test_conversation_path(): + project = "scallop" + location = "abalone" + data_store = "squid" + conversation = "clam" expected = "projects/{project}/locations/{location}/dataStores/{data_store}/conversations/{conversation}".format( project=project, location=location, @@ -5851,10 +10228,10 @@ def test_conversation_path(): def test_parse_conversation_path(): expected = { - "project": "oyster", - "location": "nudibranch", - "data_store": "cuttlefish", - "conversation": "mussel", + "project": "whelk", + "location": "octopus", + "data_store": "oyster", + "conversation": "nudibranch", } path = ConversationalSearchServiceClient.conversation_path(**expected) @@ -5864,9 +10241,9 @@ def test_parse_conversation_path(): def test_data_store_path(): - project = "winkle" - location = "nautilus" - data_store = "scallop" + project = "cuttlefish" + location = "mussel" + data_store = "winkle" expected = "projects/{project}/locations/{location}/dataStores/{data_store}".format( project=project, location=location, @@ -5880,9 +10257,9 @@ def test_data_store_path(): def test_parse_data_store_path(): expected = { - "project": "abalone", - "location": "squid", - "data_store": "clam", + "project": "nautilus", + "location": "scallop", + "data_store": "abalone", } path = ConversationalSearchServiceClient.data_store_path(**expected) @@ -5892,11 +10269,11 @@ def test_parse_data_store_path(): def test_document_path(): - project = "whelk" - location = "octopus" - data_store = "oyster" - branch = "nudibranch" - document = "cuttlefish" + project = "squid" + location = "clam" + data_store = "whelk" + branch = "octopus" + document = "oyster" expected = "projects/{project}/locations/{location}/dataStores/{data_store}/branches/{branch}/documents/{document}".format( project=project, location=location, @@ -5912,11 +10289,11 @@ def test_document_path(): def test_parse_document_path(): expected = { - "project": "mussel", - "location": "winkle", - "data_store": "nautilus", - "branch": "scallop", - "document": "abalone", + "project": "nudibranch", + "location": "cuttlefish", + "data_store": "mussel", + "branch": "winkle", + "document": "nautilus", } path = ConversationalSearchServiceClient.document_path(**expected) @@ -5926,10 +10303,10 @@ def test_parse_document_path(): def test_serving_config_path(): - project = "squid" - location = "clam" - data_store = "whelk" - serving_config = "octopus" + project = "scallop" + location = "abalone" + data_store = "squid" + serving_config = "clam" expected = "projects/{project}/locations/{location}/dataStores/{data_store}/servingConfigs/{serving_config}".format( project=project, location=location, @@ -5944,10 +10321,10 @@ def test_serving_config_path(): def test_parse_serving_config_path(): expected = { - "project": "oyster", - "location": "nudibranch", - "data_store": "cuttlefish", - "serving_config": "mussel", + "project": "whelk", + "location": "octopus", + "data_store": "oyster", + "serving_config": "nudibranch", } path = ConversationalSearchServiceClient.serving_config_path(**expected) @@ -5956,8 +10333,39 @@ def test_parse_serving_config_path(): assert expected == actual +def test_session_path(): + project = "cuttlefish" + location = "mussel" + data_store = "winkle" + session = "nautilus" + expected = "projects/{project}/locations/{location}/dataStores/{data_store}/sessions/{session}".format( + project=project, + location=location, + data_store=data_store, + session=session, + ) + actual = ConversationalSearchServiceClient.session_path( + project, location, data_store, session + ) + assert expected == actual + + +def test_parse_session_path(): + expected = { + "project": "scallop", + "location": "abalone", + "data_store": "squid", + "session": "clam", + } + path = ConversationalSearchServiceClient.session_path(**expected) + + # Check that the path construction is reversible. + actual = ConversationalSearchServiceClient.parse_session_path(path) + assert expected == actual + + def test_common_billing_account_path(): - billing_account = "winkle" + billing_account = "whelk" expected = "billingAccounts/{billing_account}".format( billing_account=billing_account, ) @@ -5969,7 +10377,7 @@ def test_common_billing_account_path(): def test_parse_common_billing_account_path(): expected = { - "billing_account": "nautilus", + "billing_account": "octopus", } path = ConversationalSearchServiceClient.common_billing_account_path(**expected) @@ -5979,7 +10387,7 @@ def test_parse_common_billing_account_path(): def test_common_folder_path(): - folder = "scallop" + folder = "oyster" expected = "folders/{folder}".format( folder=folder, ) @@ -5989,7 +10397,7 @@ def test_common_folder_path(): def test_parse_common_folder_path(): expected = { - "folder": "abalone", + "folder": "nudibranch", } path = ConversationalSearchServiceClient.common_folder_path(**expected) @@ -5999,7 +10407,7 @@ def test_parse_common_folder_path(): def test_common_organization_path(): - organization = "squid" + organization = "cuttlefish" expected = "organizations/{organization}".format( organization=organization, ) @@ -6009,7 +10417,7 @@ def test_common_organization_path(): def test_parse_common_organization_path(): expected = { - "organization": "clam", + "organization": "mussel", } path = ConversationalSearchServiceClient.common_organization_path(**expected) @@ -6019,7 +10427,7 @@ def test_parse_common_organization_path(): def test_common_project_path(): - project = "whelk" + project = "winkle" expected = "projects/{project}".format( project=project, ) @@ -6029,7 +10437,7 @@ def test_common_project_path(): def test_parse_common_project_path(): expected = { - "project": "octopus", + "project": "nautilus", } path = ConversationalSearchServiceClient.common_project_path(**expected) @@ -6039,8 +10447,8 @@ def test_parse_common_project_path(): def test_common_location_path(): - project = "oyster" - location = "nudibranch" + project = "scallop" + location = "abalone" expected = "projects/{project}/locations/{location}".format( project=project, location=location, @@ -6051,8 +10459,8 @@ def test_common_location_path(): def test_parse_common_location_path(): expected = { - "project": "cuttlefish", - "location": "mussel", + "project": "squid", + "location": "clam", } path = ConversationalSearchServiceClient.common_location_path(**expected) diff --git a/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1beta/test_document_service.py b/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1beta/test_document_service.py index b783b50e0088..a91172d452e0 100644 --- a/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1beta/test_document_service.py +++ b/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1beta/test_document_service.py @@ -44,6 +44,7 @@ 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 from google.protobuf import struct_pb2 # type: ignore from google.protobuf import timestamp_pb2 # type: ignore @@ -2316,7 +2317,7 @@ def test_update_document(request_type, transport: str = "grpc"): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.update_document), "__call__") as call: # Designate an appropriate return value for the call. - call.return_value = document.Document( + call.return_value = gcd_document.Document( name="name_value", id="id_value", schema_id="schema_id_value", @@ -2332,7 +2333,7 @@ def test_update_document(request_type, transport: str = "grpc"): assert args[0] == request # Establish that the response is the type that we expect. - assert isinstance(response, document.Document) + assert isinstance(response, gcd_document.Document) assert response.name == "name_value" assert response.id == "id_value" assert response.schema_id == "schema_id_value" @@ -2389,7 +2390,7 @@ async def test_update_document_empty_call_async(): with mock.patch.object(type(client.transport.update_document), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( - document.Document( + gcd_document.Document( name="name_value", id="id_value", schema_id="schema_id_value", @@ -2419,7 +2420,7 @@ async def test_update_document_async( with mock.patch.object(type(client.transport.update_document), "__call__") as call: # Designate an appropriate return value for the call. call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( - document.Document( + gcd_document.Document( name="name_value", id="id_value", schema_id="schema_id_value", @@ -2435,7 +2436,7 @@ async def test_update_document_async( assert args[0] == request # Establish that the response is the type that we expect. - assert isinstance(response, document.Document) + assert isinstance(response, gcd_document.Document) assert response.name == "name_value" assert response.id == "id_value" assert response.schema_id == "schema_id_value" @@ -2460,7 +2461,7 @@ def test_update_document_field_headers(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.update_document), "__call__") as call: - call.return_value = document.Document() + call.return_value = gcd_document.Document() client.update_document(request) # Establish that the underlying gRPC stub method was called. @@ -2490,7 +2491,9 @@ async def test_update_document_field_headers_async(): # Mock the actual call within the gRPC stub, and fake the request. with mock.patch.object(type(client.transport.update_document), "__call__") as call: - call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(document.Document()) + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + gcd_document.Document() + ) await client.update_document(request) # Establish that the underlying gRPC stub method was called. @@ -2506,6 +2509,146 @@ async def test_update_document_field_headers_async(): ) in kw["metadata"] +def test_update_document_flattened(): + client = DocumentServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.update_document), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = gcd_document.Document() + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.update_document( + document=gcd_document.Document( + struct_data=struct_pb2.Struct( + fields={ + "key_value": struct_pb2.Value( + null_value=struct_pb2.NullValue.NULL_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].document + mock_val = gcd_document.Document( + struct_data=struct_pb2.Struct( + fields={ + "key_value": struct_pb2.Value( + null_value=struct_pb2.NullValue.NULL_VALUE + ) + } + ) + ) + assert arg == mock_val + arg = args[0].update_mask + mock_val = field_mask_pb2.FieldMask(paths=["paths_value"]) + assert arg == mock_val + + +def test_update_document_flattened_error(): + client = DocumentServiceClient( + 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_document( + document_service.UpdateDocumentRequest(), + document=gcd_document.Document( + struct_data=struct_pb2.Struct( + fields={ + "key_value": struct_pb2.Value( + null_value=struct_pb2.NullValue.NULL_VALUE + ) + } + ) + ), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + +@pytest.mark.asyncio +async def test_update_document_flattened_async(): + client = DocumentServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.update_document), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = gcd_document.Document() + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + gcd_document.Document() + ) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.update_document( + document=gcd_document.Document( + struct_data=struct_pb2.Struct( + fields={ + "key_value": struct_pb2.Value( + null_value=struct_pb2.NullValue.NULL_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].document + mock_val = gcd_document.Document( + struct_data=struct_pb2.Struct( + fields={ + "key_value": struct_pb2.Value( + null_value=struct_pb2.NullValue.NULL_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_document_flattened_error_async(): + client = DocumentServiceAsyncClient( + 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_document( + document_service.UpdateDocumentRequest(), + document=gcd_document.Document( + struct_data=struct_pb2.Struct( + fields={ + "key_value": struct_pb2.Value( + null_value=struct_pb2.NullValue.NULL_VALUE + ) + } + ) + ), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + @pytest.mark.parametrize( "request_type", [ @@ -4298,7 +4441,7 @@ def get_message_fields(field): # 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 = document.Document( + return_value = gcd_document.Document( name="name_value", id="id_value", schema_id="schema_id_value", @@ -4310,7 +4453,7 @@ def get_message_fields(field): response_value = Response() response_value.status_code = 200 # Convert return value to protobuf type - return_value = document.Document.pb(return_value) + return_value = gcd_document.Document.pb(return_value) json_return_value = json_format.MessageToJson(return_value) response_value._content = json_return_value.encode("UTF-8") @@ -4318,7 +4461,7 @@ def get_message_fields(field): response = client.update_document(request) # Establish that the response is the type that we expect. - assert isinstance(response, document.Document) + assert isinstance(response, gcd_document.Document) assert response.name == "name_value" assert response.id == "id_value" assert response.schema_id == "schema_id_value" @@ -4350,7 +4493,12 @@ def test_update_document_rest_required_fields( credentials=ga_credentials.AnonymousCredentials() ).update_document._get_unset_required_fields(jsonified_request) # Check that path parameters and body parameters are not mixing in. - assert not set(unset_fields) - set(("allow_missing",)) + assert not set(unset_fields) - set( + ( + "allow_missing", + "update_mask", + ) + ) jsonified_request.update(unset_fields) # verify required fields with non-default values are left alone @@ -4362,7 +4510,7 @@ def test_update_document_rest_required_fields( request = request_type(**request_init) # Designate an appropriate value for the returned response. - return_value = document.Document() + return_value = gcd_document.Document() # 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 @@ -4384,7 +4532,7 @@ def test_update_document_rest_required_fields( response_value.status_code = 200 # Convert return value to protobuf type - return_value = document.Document.pb(return_value) + return_value = gcd_document.Document.pb(return_value) json_return_value = json_format.MessageToJson(return_value) response_value._content = json_return_value.encode("UTF-8") @@ -4403,7 +4551,15 @@ def test_update_document_rest_unset_required_fields(): ) unset_fields = transport.update_document._get_unset_required_fields({}) - assert set(unset_fields) == (set(("allowMissing",)) & set(("document",))) + assert set(unset_fields) == ( + set( + ( + "allowMissing", + "updateMask", + ) + ) + & set(("document",)) + ) @pytest.mark.parametrize("null_interceptor", [True, False]) @@ -4439,7 +4595,9 @@ def test_update_document_rest_interceptors(null_interceptor): req.return_value = Response() req.return_value.status_code = 200 req.return_value.request = PreparedRequest() - req.return_value._content = document.Document.to_json(document.Document()) + req.return_value._content = gcd_document.Document.to_json( + gcd_document.Document() + ) request = document_service.UpdateDocumentRequest() metadata = [ @@ -4447,7 +4605,7 @@ def test_update_document_rest_interceptors(null_interceptor): ("cephalopod", "squid"), ] pre.return_value = request, metadata - post.return_value = document.Document() + post.return_value = gcd_document.Document() client.update_document( request, @@ -4489,6 +4647,85 @@ def test_update_document_rest_bad_request( client.update_document(request) +def test_update_document_rest_flattened(): + client = DocumentServiceClient( + 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 = gcd_document.Document() + + # get arguments that satisfy an http rule for this method + sample_request = { + "document": { + "name": "projects/sample1/locations/sample2/dataStores/sample3/branches/sample4/documents/sample5" + } + } + + # get truthy value for each flattened field + mock_args = dict( + document=gcd_document.Document( + struct_data=struct_pb2.Struct( + fields={ + "key_value": struct_pb2.Value( + null_value=struct_pb2.NullValue.NULL_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 = gcd_document.Document.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_document(**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/v1beta/{document.name=projects/*/locations/*/dataStores/*/branches/*/documents/*}" + % client.transport._host, + args[1], + ) + + +def test_update_document_rest_flattened_error(transport: str = "rest"): + client = DocumentServiceClient( + 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_document( + document_service.UpdateDocumentRequest(), + document=gcd_document.Document( + struct_data=struct_pb2.Struct( + fields={ + "key_value": struct_pb2.Value( + null_value=struct_pb2.NullValue.NULL_VALUE + ) + } + ) + ), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + def test_update_document_rest_error(): client = DocumentServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest" @@ -5854,8 +6091,39 @@ def test_parse_document_path(): assert expected == actual +def test_fhir_store_path(): + project = "cuttlefish" + location = "mussel" + dataset = "winkle" + fhir_store = "nautilus" + expected = "projects/{project}/locations/{location}/datasets/{dataset}/fhirStores/{fhir_store}".format( + project=project, + location=location, + dataset=dataset, + fhir_store=fhir_store, + ) + actual = DocumentServiceClient.fhir_store_path( + project, location, dataset, fhir_store + ) + assert expected == actual + + +def test_parse_fhir_store_path(): + expected = { + "project": "scallop", + "location": "abalone", + "dataset": "squid", + "fhir_store": "clam", + } + path = DocumentServiceClient.fhir_store_path(**expected) + + # Check that the path construction is reversible. + actual = DocumentServiceClient.parse_fhir_store_path(path) + assert expected == actual + + def test_common_billing_account_path(): - billing_account = "cuttlefish" + billing_account = "whelk" expected = "billingAccounts/{billing_account}".format( billing_account=billing_account, ) @@ -5865,7 +6133,7 @@ def test_common_billing_account_path(): def test_parse_common_billing_account_path(): expected = { - "billing_account": "mussel", + "billing_account": "octopus", } path = DocumentServiceClient.common_billing_account_path(**expected) @@ -5875,7 +6143,7 @@ def test_parse_common_billing_account_path(): def test_common_folder_path(): - folder = "winkle" + folder = "oyster" expected = "folders/{folder}".format( folder=folder, ) @@ -5885,7 +6153,7 @@ def test_common_folder_path(): def test_parse_common_folder_path(): expected = { - "folder": "nautilus", + "folder": "nudibranch", } path = DocumentServiceClient.common_folder_path(**expected) @@ -5895,7 +6163,7 @@ def test_parse_common_folder_path(): def test_common_organization_path(): - organization = "scallop" + organization = "cuttlefish" expected = "organizations/{organization}".format( organization=organization, ) @@ -5905,7 +6173,7 @@ def test_common_organization_path(): def test_parse_common_organization_path(): expected = { - "organization": "abalone", + "organization": "mussel", } path = DocumentServiceClient.common_organization_path(**expected) @@ -5915,7 +6183,7 @@ def test_parse_common_organization_path(): def test_common_project_path(): - project = "squid" + project = "winkle" expected = "projects/{project}".format( project=project, ) @@ -5925,7 +6193,7 @@ def test_common_project_path(): def test_parse_common_project_path(): expected = { - "project": "clam", + "project": "nautilus", } path = DocumentServiceClient.common_project_path(**expected) @@ -5935,8 +6203,8 @@ def test_parse_common_project_path(): def test_common_location_path(): - project = "whelk" - location = "octopus" + project = "scallop" + location = "abalone" expected = "projects/{project}/locations/{location}".format( project=project, location=location, @@ -5947,8 +6215,8 @@ def test_common_location_path(): def test_parse_common_location_path(): expected = { - "project": "oyster", - "location": "nudibranch", + "project": "squid", + "location": "clam", } path = DocumentServiceClient.common_location_path(**expected) diff --git a/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1beta/test_engine_service.py b/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1beta/test_engine_service.py index 8873d59088bd..700620079c4a 100644 --- a/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1beta/test_engine_service.py +++ b/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1beta/test_engine_service.py @@ -2849,6 +2849,876 @@ async def test_list_engines_async_pages(): assert page_.raw_page.next_page_token == token +@pytest.mark.parametrize( + "request_type", + [ + engine_service.PauseEngineRequest, + dict, + ], +) +def test_pause_engine(request_type, transport: str = "grpc"): + client = EngineServiceClient( + 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.pause_engine), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = engine.Engine( + name="name_value", + display_name="display_name_value", + data_store_ids=["data_store_ids_value"], + solution_type=common.SolutionType.SOLUTION_TYPE_RECOMMENDATION, + industry_vertical=common.IndustryVertical.GENERIC, + ) + response = client.pause_engine(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = engine_service.PauseEngineRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, engine.Engine) + assert response.name == "name_value" + assert response.display_name == "display_name_value" + assert response.data_store_ids == ["data_store_ids_value"] + assert response.solution_type == common.SolutionType.SOLUTION_TYPE_RECOMMENDATION + assert response.industry_vertical == common.IndustryVertical.GENERIC + + +def test_pause_engine_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 = EngineServiceClient( + 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.pause_engine), "__call__") as call: + client.pause_engine() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == engine_service.PauseEngineRequest() + + +def test_pause_engine_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 = EngineServiceClient( + 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 = engine_service.PauseEngineRequest( + name="name_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.pause_engine), "__call__") as call: + client.pause_engine(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == engine_service.PauseEngineRequest( + name="name_value", + ) + + +@pytest.mark.asyncio +async def test_pause_engine_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 = EngineServiceAsyncClient( + 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.pause_engine), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + engine.Engine( + name="name_value", + display_name="display_name_value", + data_store_ids=["data_store_ids_value"], + solution_type=common.SolutionType.SOLUTION_TYPE_RECOMMENDATION, + industry_vertical=common.IndustryVertical.GENERIC, + ) + ) + response = await client.pause_engine() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == engine_service.PauseEngineRequest() + + +@pytest.mark.asyncio +async def test_pause_engine_async( + transport: str = "grpc_asyncio", request_type=engine_service.PauseEngineRequest +): + client = EngineServiceAsyncClient( + 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.pause_engine), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + engine.Engine( + name="name_value", + display_name="display_name_value", + data_store_ids=["data_store_ids_value"], + solution_type=common.SolutionType.SOLUTION_TYPE_RECOMMENDATION, + industry_vertical=common.IndustryVertical.GENERIC, + ) + ) + response = await client.pause_engine(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = engine_service.PauseEngineRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, engine.Engine) + assert response.name == "name_value" + assert response.display_name == "display_name_value" + assert response.data_store_ids == ["data_store_ids_value"] + assert response.solution_type == common.SolutionType.SOLUTION_TYPE_RECOMMENDATION + assert response.industry_vertical == common.IndustryVertical.GENERIC + + +@pytest.mark.asyncio +async def test_pause_engine_async_from_dict(): + await test_pause_engine_async(request_type=dict) + + +def test_pause_engine_field_headers(): + client = EngineServiceClient( + 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 = engine_service.PauseEngineRequest() + + request.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.pause_engine), "__call__") as call: + call.return_value = engine.Engine() + client.pause_engine(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_pause_engine_field_headers_async(): + client = EngineServiceAsyncClient( + 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 = engine_service.PauseEngineRequest() + + request.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.pause_engine), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(engine.Engine()) + await client.pause_engine(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_pause_engine_flattened(): + client = EngineServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.pause_engine), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = engine.Engine() + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.pause_engine( + 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_pause_engine_flattened_error(): + client = EngineServiceClient( + 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.pause_engine( + engine_service.PauseEngineRequest(), + name="name_value", + ) + + +@pytest.mark.asyncio +async def test_pause_engine_flattened_async(): + client = EngineServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.pause_engine), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = engine.Engine() + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(engine.Engine()) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.pause_engine( + 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_pause_engine_flattened_error_async(): + client = EngineServiceAsyncClient( + 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.pause_engine( + engine_service.PauseEngineRequest(), + name="name_value", + ) + + +@pytest.mark.parametrize( + "request_type", + [ + engine_service.ResumeEngineRequest, + dict, + ], +) +def test_resume_engine(request_type, transport: str = "grpc"): + client = EngineServiceClient( + 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.resume_engine), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = engine.Engine( + name="name_value", + display_name="display_name_value", + data_store_ids=["data_store_ids_value"], + solution_type=common.SolutionType.SOLUTION_TYPE_RECOMMENDATION, + industry_vertical=common.IndustryVertical.GENERIC, + ) + response = client.resume_engine(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = engine_service.ResumeEngineRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, engine.Engine) + assert response.name == "name_value" + assert response.display_name == "display_name_value" + assert response.data_store_ids == ["data_store_ids_value"] + assert response.solution_type == common.SolutionType.SOLUTION_TYPE_RECOMMENDATION + assert response.industry_vertical == common.IndustryVertical.GENERIC + + +def test_resume_engine_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 = EngineServiceClient( + 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.resume_engine), "__call__") as call: + client.resume_engine() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == engine_service.ResumeEngineRequest() + + +def test_resume_engine_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 = EngineServiceClient( + 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 = engine_service.ResumeEngineRequest( + name="name_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.resume_engine), "__call__") as call: + client.resume_engine(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == engine_service.ResumeEngineRequest( + name="name_value", + ) + + +@pytest.mark.asyncio +async def test_resume_engine_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 = EngineServiceAsyncClient( + 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.resume_engine), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + engine.Engine( + name="name_value", + display_name="display_name_value", + data_store_ids=["data_store_ids_value"], + solution_type=common.SolutionType.SOLUTION_TYPE_RECOMMENDATION, + industry_vertical=common.IndustryVertical.GENERIC, + ) + ) + response = await client.resume_engine() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == engine_service.ResumeEngineRequest() + + +@pytest.mark.asyncio +async def test_resume_engine_async( + transport: str = "grpc_asyncio", request_type=engine_service.ResumeEngineRequest +): + client = EngineServiceAsyncClient( + 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.resume_engine), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + engine.Engine( + name="name_value", + display_name="display_name_value", + data_store_ids=["data_store_ids_value"], + solution_type=common.SolutionType.SOLUTION_TYPE_RECOMMENDATION, + industry_vertical=common.IndustryVertical.GENERIC, + ) + ) + response = await client.resume_engine(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = engine_service.ResumeEngineRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, engine.Engine) + assert response.name == "name_value" + assert response.display_name == "display_name_value" + assert response.data_store_ids == ["data_store_ids_value"] + assert response.solution_type == common.SolutionType.SOLUTION_TYPE_RECOMMENDATION + assert response.industry_vertical == common.IndustryVertical.GENERIC + + +@pytest.mark.asyncio +async def test_resume_engine_async_from_dict(): + await test_resume_engine_async(request_type=dict) + + +def test_resume_engine_field_headers(): + client = EngineServiceClient( + 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 = engine_service.ResumeEngineRequest() + + request.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.resume_engine), "__call__") as call: + call.return_value = engine.Engine() + client.resume_engine(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_resume_engine_field_headers_async(): + client = EngineServiceAsyncClient( + 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 = engine_service.ResumeEngineRequest() + + request.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.resume_engine), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(engine.Engine()) + await client.resume_engine(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_resume_engine_flattened(): + client = EngineServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.resume_engine), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = engine.Engine() + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.resume_engine( + 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_resume_engine_flattened_error(): + client = EngineServiceClient( + 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.resume_engine( + engine_service.ResumeEngineRequest(), + name="name_value", + ) + + +@pytest.mark.asyncio +async def test_resume_engine_flattened_async(): + client = EngineServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.resume_engine), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = engine.Engine() + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(engine.Engine()) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.resume_engine( + 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_resume_engine_flattened_error_async(): + client = EngineServiceAsyncClient( + 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.resume_engine( + engine_service.ResumeEngineRequest(), + name="name_value", + ) + + +@pytest.mark.parametrize( + "request_type", + [ + engine_service.TuneEngineRequest, + dict, + ], +) +def test_tune_engine(request_type, transport: str = "grpc"): + client = EngineServiceClient( + 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.tune_engine), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.Operation(name="operations/spam") + response = client.tune_engine(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = engine_service.TuneEngineRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, future.Future) + + +def test_tune_engine_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 = EngineServiceClient( + 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.tune_engine), "__call__") as call: + client.tune_engine() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == engine_service.TuneEngineRequest() + + +def test_tune_engine_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 = EngineServiceClient( + 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 = engine_service.TuneEngineRequest( + name="name_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.tune_engine), "__call__") as call: + client.tune_engine(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == engine_service.TuneEngineRequest( + name="name_value", + ) + + +@pytest.mark.asyncio +async def test_tune_engine_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 = EngineServiceAsyncClient( + 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.tune_engine), "__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.tune_engine() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == engine_service.TuneEngineRequest() + + +@pytest.mark.asyncio +async def test_tune_engine_async( + transport: str = "grpc_asyncio", request_type=engine_service.TuneEngineRequest +): + client = EngineServiceAsyncClient( + 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.tune_engine), "__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.tune_engine(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = engine_service.TuneEngineRequest() + 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_tune_engine_async_from_dict(): + await test_tune_engine_async(request_type=dict) + + +def test_tune_engine_field_headers(): + client = EngineServiceClient( + 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 = engine_service.TuneEngineRequest() + + request.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.tune_engine), "__call__") as call: + call.return_value = operations_pb2.Operation(name="operations/op") + client.tune_engine(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_tune_engine_field_headers_async(): + client = EngineServiceAsyncClient( + 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 = engine_service.TuneEngineRequest() + + request.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.tune_engine), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/op") + ) + await client.tune_engine(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_tune_engine_flattened(): + client = EngineServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.tune_engine), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.Operation(name="operations/op") + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.tune_engine( + 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_tune_engine_flattened_error(): + client = EngineServiceClient( + 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.tune_engine( + engine_service.TuneEngineRequest(), + name="name_value", + ) + + +@pytest.mark.asyncio +async def test_tune_engine_flattened_async(): + client = EngineServiceAsyncClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.tune_engine), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.Operation(name="operations/op") + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/spam") + ) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.tune_engine( + 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_tune_engine_flattened_error_async(): + client = EngineServiceAsyncClient( + 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.tune_engine( + engine_service.TuneEngineRequest(), + name="name_value", + ) + + @pytest.mark.parametrize( "request_type", [ @@ -2856,130 +3726,1094 @@ async def test_list_engines_async_pages(): dict, ], ) -def test_create_engine_rest(request_type): +def test_create_engine_rest(request_type): + client = EngineServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = {"parent": "projects/sample1/locations/sample2/collections/sample3"} + request_init["engine"] = { + "chat_engine_config": { + "agent_creation_config": { + "business": "business_value", + "default_language_code": "default_language_code_value", + "time_zone": "time_zone_value", + "location": "location_value", + }, + "dialogflow_agent_to_link": "dialogflow_agent_to_link_value", + }, + "search_engine_config": {"search_tier": 1, "search_add_ons": [1]}, + "chat_engine_metadata": {"dialogflow_agent": "dialogflow_agent_value"}, + "name": "name_value", + "display_name": "display_name_value", + "create_time": {"seconds": 751, "nanos": 543}, + "update_time": {}, + "data_store_ids": ["data_store_ids_value1", "data_store_ids_value2"], + "solution_type": 1, + "industry_vertical": 1, + "common_config": {"company_name": "company_name_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 = engine_service.CreateEngineRequest.meta.fields["engine"] + + 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["engine"].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["engine"][field])): + del request_init["engine"][field][i][subfield] + else: + del request_init["engine"][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 = 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.create_engine(request) + + # Establish that the response is the type that we expect. + assert response.operation.name == "operations/spam" + + +def test_create_engine_rest_required_fields( + request_type=engine_service.CreateEngineRequest, +): + transport_class = transports.EngineServiceRestTransport + + request_init = {} + request_init["parent"] = "" + request_init["engine_id"] = "" + 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 + assert "engineId" not in jsonified_request + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).create_engine._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + assert "engineId" in jsonified_request + assert jsonified_request["engineId"] == request_init["engine_id"] + + jsonified_request["parent"] = "parent_value" + jsonified_request["engineId"] = "engine_id_value" + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).create_engine._get_unset_required_fields(jsonified_request) + # Check that path parameters and body parameters are not mixing in. + assert not set(unset_fields) - set(("engine_id",)) + 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" + assert "engineId" in jsonified_request + assert jsonified_request["engineId"] == "engine_id_value" + + client = EngineServiceClient( + 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.create_engine(request) + + expected_params = [ + ( + "engineId", + "", + ), + ("$alt", "json;enum-encoding=int"), + ] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_create_engine_rest_unset_required_fields(): + transport = transports.EngineServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.create_engine._get_unset_required_fields({}) + assert set(unset_fields) == ( + set(("engineId",)) + & set( + ( + "parent", + "engine", + "engineId", + ) + ) + ) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_create_engine_rest_interceptors(null_interceptor): + transport = transports.EngineServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.EngineServiceRestInterceptor(), + ) + client = EngineServiceClient(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.EngineServiceRestInterceptor, "post_create_engine" + ) as post, mock.patch.object( + transports.EngineServiceRestInterceptor, "pre_create_engine" + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = engine_service.CreateEngineRequest.pb( + engine_service.CreateEngineRequest() + ) + 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 = engine_service.CreateEngineRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = operations_pb2.Operation() + + client.create_engine( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_create_engine_rest_bad_request( + transport: str = "rest", request_type=engine_service.CreateEngineRequest +): + client = EngineServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = {"parent": "projects/sample1/locations/sample2/collections/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.create_engine(request) + + +def test_create_engine_rest_flattened(): + client = EngineServiceClient( + 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 = operations_pb2.Operation(name="operations/spam") + + # get arguments that satisfy an http rule for this method + sample_request = { + "parent": "projects/sample1/locations/sample2/collections/sample3" + } + + # get truthy value for each flattened field + mock_args = dict( + parent="parent_value", + engine=gcd_engine.Engine( + chat_engine_config=gcd_engine.Engine.ChatEngineConfig( + agent_creation_config=gcd_engine.Engine.ChatEngineConfig.AgentCreationConfig( + business="business_value" + ) + ) + ), + engine_id="engine_id_value", + ) + mock_args.update(sample_request) + + # 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 + + client.create_engine(**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/v1beta/{parent=projects/*/locations/*/collections/*}/engines" + % client.transport._host, + args[1], + ) + + +def test_create_engine_rest_flattened_error(transport: str = "rest"): + client = EngineServiceClient( + 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.create_engine( + engine_service.CreateEngineRequest(), + parent="parent_value", + engine=gcd_engine.Engine( + chat_engine_config=gcd_engine.Engine.ChatEngineConfig( + agent_creation_config=gcd_engine.Engine.ChatEngineConfig.AgentCreationConfig( + business="business_value" + ) + ) + ), + engine_id="engine_id_value", + ) + + +def test_create_engine_rest_error(): + client = EngineServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + +@pytest.mark.parametrize( + "request_type", + [ + engine_service.DeleteEngineRequest, + dict, + ], +) +def test_delete_engine_rest(request_type): + client = EngineServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = { + "name": "projects/sample1/locations/sample2/collections/sample3/engines/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.delete_engine(request) + + # Establish that the response is the type that we expect. + assert response.operation.name == "operations/spam" + + +def test_delete_engine_rest_required_fields( + request_type=engine_service.DeleteEngineRequest, +): + transport_class = transports.EngineServiceRestTransport + + 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() + ).delete_engine._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() + ).delete_engine._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 = EngineServiceClient( + 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": "delete", + "query_params": 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.delete_engine(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_delete_engine_rest_unset_required_fields(): + transport = transports.EngineServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.delete_engine._get_unset_required_fields({}) + assert set(unset_fields) == (set(()) & set(("name",))) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_delete_engine_rest_interceptors(null_interceptor): + transport = transports.EngineServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.EngineServiceRestInterceptor(), + ) + client = EngineServiceClient(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.EngineServiceRestInterceptor, "post_delete_engine" + ) as post, mock.patch.object( + transports.EngineServiceRestInterceptor, "pre_delete_engine" + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = engine_service.DeleteEngineRequest.pb( + engine_service.DeleteEngineRequest() + ) + 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 = engine_service.DeleteEngineRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = operations_pb2.Operation() + + client.delete_engine( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_delete_engine_rest_bad_request( + transport: str = "rest", request_type=engine_service.DeleteEngineRequest +): + client = EngineServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = { + "name": "projects/sample1/locations/sample2/collections/sample3/engines/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.delete_engine(request) + + +def test_delete_engine_rest_flattened(): + client = EngineServiceClient( + 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 = operations_pb2.Operation(name="operations/spam") + + # get arguments that satisfy an http rule for this method + sample_request = { + "name": "projects/sample1/locations/sample2/collections/sample3/engines/sample4" + } + + # 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 + json_return_value = json_format.MessageToJson(return_value) + response_value._content = json_return_value.encode("UTF-8") + req.return_value = response_value + + client.delete_engine(**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/v1beta/{name=projects/*/locations/*/collections/*/engines/*}" + % client.transport._host, + args[1], + ) + + +def test_delete_engine_rest_flattened_error(transport: str = "rest"): + client = EngineServiceClient( + 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.delete_engine( + engine_service.DeleteEngineRequest(), + name="name_value", + ) + + +def test_delete_engine_rest_error(): + client = EngineServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + +@pytest.mark.parametrize( + "request_type", + [ + engine_service.UpdateEngineRequest, + dict, + ], +) +def test_update_engine_rest(request_type): + client = EngineServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = { + "engine": { + "name": "projects/sample1/locations/sample2/collections/sample3/engines/sample4" + } + } + request_init["engine"] = { + "chat_engine_config": { + "agent_creation_config": { + "business": "business_value", + "default_language_code": "default_language_code_value", + "time_zone": "time_zone_value", + "location": "location_value", + }, + "dialogflow_agent_to_link": "dialogflow_agent_to_link_value", + }, + "search_engine_config": {"search_tier": 1, "search_add_ons": [1]}, + "chat_engine_metadata": {"dialogflow_agent": "dialogflow_agent_value"}, + "name": "projects/sample1/locations/sample2/collections/sample3/engines/sample4", + "display_name": "display_name_value", + "create_time": {"seconds": 751, "nanos": 543}, + "update_time": {}, + "data_store_ids": ["data_store_ids_value1", "data_store_ids_value2"], + "solution_type": 1, + "industry_vertical": 1, + "common_config": {"company_name": "company_name_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 = engine_service.UpdateEngineRequest.meta.fields["engine"] + + 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["engine"].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["engine"][field])): + del request_init["engine"][field][i][subfield] + else: + del request_init["engine"][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 = gcd_engine.Engine( + name="name_value", + display_name="display_name_value", + data_store_ids=["data_store_ids_value"], + solution_type=common.SolutionType.SOLUTION_TYPE_RECOMMENDATION, + industry_vertical=common.IndustryVertical.GENERIC, + ) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = gcd_engine.Engine.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_engine(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, gcd_engine.Engine) + assert response.name == "name_value" + assert response.display_name == "display_name_value" + assert response.data_store_ids == ["data_store_ids_value"] + assert response.solution_type == common.SolutionType.SOLUTION_TYPE_RECOMMENDATION + assert response.industry_vertical == common.IndustryVertical.GENERIC + + +def test_update_engine_rest_required_fields( + request_type=engine_service.UpdateEngineRequest, +): + transport_class = transports.EngineServiceRestTransport + + 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_engine._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_engine._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 = EngineServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = gcd_engine.Engine() + # 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 = gcd_engine.Engine.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_engine(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_update_engine_rest_unset_required_fields(): + transport = transports.EngineServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.update_engine._get_unset_required_fields({}) + assert set(unset_fields) == (set(("updateMask",)) & set(("engine",))) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_update_engine_rest_interceptors(null_interceptor): + transport = transports.EngineServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.EngineServiceRestInterceptor(), + ) + client = EngineServiceClient(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.EngineServiceRestInterceptor, "post_update_engine" + ) as post, mock.patch.object( + transports.EngineServiceRestInterceptor, "pre_update_engine" + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = engine_service.UpdateEngineRequest.pb( + engine_service.UpdateEngineRequest() + ) + 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 = gcd_engine.Engine.to_json(gcd_engine.Engine()) + + request = engine_service.UpdateEngineRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = gcd_engine.Engine() + + client.update_engine( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_update_engine_rest_bad_request( + transport: str = "rest", request_type=engine_service.UpdateEngineRequest +): + client = EngineServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) # send a request that will satisfy transcoding - request_init = {"parent": "projects/sample1/locations/sample2/collections/sample3"} - request_init["engine"] = { - "chat_engine_config": { - "agent_creation_config": { - "business": "business_value", - "default_language_code": "default_language_code_value", - "time_zone": "time_zone_value", - "location": "location_value", - }, - "dialogflow_agent_to_link": "dialogflow_agent_to_link_value", - }, - "search_engine_config": {"search_tier": 1, "search_add_ons": [1]}, - "chat_engine_metadata": {"dialogflow_agent": "dialogflow_agent_value"}, - "name": "name_value", - "display_name": "display_name_value", - "create_time": {"seconds": 751, "nanos": 543}, - "update_time": {}, - "data_store_ids": ["data_store_ids_value1", "data_store_ids_value2"], - "solution_type": 1, - "industry_vertical": 1, - "common_config": {"company_name": "company_name_value"}, + request_init = { + "engine": { + "name": "projects/sample1/locations/sample2/collections/sample3/engines/sample4" + } } - # 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 + request = request_type(**request_init) - # Determine if the message type is proto-plus or protobuf - test_field = engine_service.CreateEngineRequest.meta.fields["engine"] + # 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_engine(request) - 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") +def test_update_engine_rest_flattened(): + client = EngineServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) - 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 + # 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 = gcd_engine.Engine() + + # get arguments that satisfy an http rule for this method + sample_request = { + "engine": { + "name": "projects/sample1/locations/sample2/collections/sample3/engines/sample4" + } + } + + # get truthy value for each flattened field + mock_args = dict( + engine=gcd_engine.Engine( + chat_engine_config=gcd_engine.Engine.ChatEngineConfig( + agent_creation_config=gcd_engine.Engine.ChatEngineConfig.AgentCreationConfig( + business="business_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 = gcd_engine.Engine.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_engine(**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/v1beta/{engine.name=projects/*/locations/*/collections/*/engines/*}" + % client.transport._host, + args[1], + ) + + +def test_update_engine_rest_flattened_error(transport: str = "rest"): + client = EngineServiceClient( + 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_engine( + engine_service.UpdateEngineRequest(), + engine=gcd_engine.Engine( + chat_engine_config=gcd_engine.Engine.ChatEngineConfig( + agent_creation_config=gcd_engine.Engine.ChatEngineConfig.AgentCreationConfig( + business="business_value" + ) + ) + ), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) - 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 = [] +def test_update_engine_rest_error(): + client = EngineServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) - # 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["engine"].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, - } - ) +@pytest.mark.parametrize( + "request_type", + [ + engine_service.GetEngineRequest, + dict, + ], +) +def test_get_engine_rest(request_type): + client = EngineServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) - # 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["engine"][field])): - del request_init["engine"][field][i][subfield] - else: - del request_init["engine"][field][subfield] + # send a request that will satisfy transcoding + request_init = { + "name": "projects/sample1/locations/sample2/collections/sample3/engines/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") + return_value = engine.Engine( + name="name_value", + display_name="display_name_value", + data_store_ids=["data_store_ids_value"], + solution_type=common.SolutionType.SOLUTION_TYPE_RECOMMENDATION, + industry_vertical=common.IndustryVertical.GENERIC, + ) # Wrap the value into a proper Response obj response_value = Response() response_value.status_code = 200 + # Convert return value to protobuf type + return_value = engine.Engine.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.create_engine(request) + response = client.get_engine(request) # Establish that the response is the type that we expect. - assert response.operation.name == "operations/spam" + assert isinstance(response, engine.Engine) + assert response.name == "name_value" + assert response.display_name == "display_name_value" + assert response.data_store_ids == ["data_store_ids_value"] + assert response.solution_type == common.SolutionType.SOLUTION_TYPE_RECOMMENDATION + assert response.industry_vertical == common.IndustryVertical.GENERIC -def test_create_engine_rest_required_fields( - request_type=engine_service.CreateEngineRequest, -): +def test_get_engine_rest_required_fields(request_type=engine_service.GetEngineRequest): transport_class = transports.EngineServiceRestTransport request_init = {} - request_init["parent"] = "" - request_init["engine_id"] = "" + request_init["name"] = "" request = request_type(**request_init) pb_request = request_type.pb(request) jsonified_request = json.loads( @@ -2987,32 +4821,24 @@ def test_create_engine_rest_required_fields( ) # verify fields with default values are dropped - assert "engineId" not in jsonified_request unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).create_engine._get_unset_required_fields(jsonified_request) + ).get_engine._get_unset_required_fields(jsonified_request) jsonified_request.update(unset_fields) # verify required fields with default values are now present - assert "engineId" in jsonified_request - assert jsonified_request["engineId"] == request_init["engine_id"] - jsonified_request["parent"] = "parent_value" - jsonified_request["engineId"] = "engine_id_value" + jsonified_request["name"] = "name_value" unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).create_engine._get_unset_required_fields(jsonified_request) - # Check that path parameters and body parameters are not mixing in. - assert not set(unset_fields) - set(("engine_id",)) + ).get_engine._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" - assert "engineId" in jsonified_request - assert jsonified_request["engineId"] == "engine_id_value" + assert "name" in jsonified_request + assert jsonified_request["name"] == "name_value" client = EngineServiceClient( credentials=ga_credentials.AnonymousCredentials(), @@ -3021,7 +4847,7 @@ def test_create_engine_rest_required_fields( request = request_type(**request_init) # Designate an appropriate value for the returned response. - return_value = operations_pb2.Operation(name="operations/spam") + return_value = engine.Engine() # 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 @@ -3033,52 +4859,39 @@ def test_create_engine_rest_required_fields( pb_request = request_type.pb(request) transcode_result = { "uri": "v1/sample_method", - "method": "post", + "method": "get", "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 = engine.Engine.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.create_engine(request) + response = client.get_engine(request) - expected_params = [ - ( - "engineId", - "", - ), - ("$alt", "json;enum-encoding=int"), - ] + expected_params = [("$alt", "json;enum-encoding=int")] actual_params = req.call_args.kwargs["params"] assert expected_params == actual_params -def test_create_engine_rest_unset_required_fields(): +def test_get_engine_rest_unset_required_fields(): transport = transports.EngineServiceRestTransport( credentials=ga_credentials.AnonymousCredentials ) - unset_fields = transport.create_engine._get_unset_required_fields({}) - assert set(unset_fields) == ( - set(("engineId",)) - & set( - ( - "parent", - "engine", - "engineId", - ) - ) - ) + unset_fields = transport.get_engine._get_unset_required_fields({}) + assert set(unset_fields) == (set(()) & set(("name",))) @pytest.mark.parametrize("null_interceptor", [True, False]) -def test_create_engine_rest_interceptors(null_interceptor): +def test_get_engine_rest_interceptors(null_interceptor): transport = transports.EngineServiceRestTransport( credentials=ga_credentials.AnonymousCredentials(), interceptor=None @@ -3091,16 +4904,14 @@ def test_create_engine_rest_interceptors(null_interceptor): ) as req, mock.patch.object( path_template, "transcode" ) as transcode, mock.patch.object( - operation.Operation, "_set_result_from_operation" - ), mock.patch.object( - transports.EngineServiceRestInterceptor, "post_create_engine" + transports.EngineServiceRestInterceptor, "post_get_engine" ) as post, mock.patch.object( - transports.EngineServiceRestInterceptor, "pre_create_engine" + transports.EngineServiceRestInterceptor, "pre_get_engine" ) as pre: pre.assert_not_called() post.assert_not_called() - pb_message = engine_service.CreateEngineRequest.pb( - engine_service.CreateEngineRequest() + pb_message = engine_service.GetEngineRequest.pb( + engine_service.GetEngineRequest() ) transcode.return_value = { "method": "post", @@ -3112,19 +4923,17 @@ def test_create_engine_rest_interceptors(null_interceptor): 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() - ) + req.return_value._content = engine.Engine.to_json(engine.Engine()) - request = engine_service.CreateEngineRequest() + request = engine_service.GetEngineRequest() metadata = [ ("key", "val"), ("cephalopod", "squid"), ] pre.return_value = request, metadata - post.return_value = operations_pb2.Operation() + post.return_value = engine.Engine() - client.create_engine( + client.get_engine( request, metadata=[ ("key", "val"), @@ -3136,8 +4945,8 @@ def test_create_engine_rest_interceptors(null_interceptor): post.assert_called_once() -def test_create_engine_rest_bad_request( - transport: str = "rest", request_type=engine_service.CreateEngineRequest +def test_get_engine_rest_bad_request( + transport: str = "rest", request_type=engine_service.GetEngineRequest ): client = EngineServiceClient( credentials=ga_credentials.AnonymousCredentials(), @@ -3145,7 +4954,9 @@ def test_create_engine_rest_bad_request( ) # send a request that will satisfy transcoding - request_init = {"parent": "projects/sample1/locations/sample2/collections/sample3"} + request_init = { + "name": "projects/sample1/locations/sample2/collections/sample3/engines/sample4" + } request = request_type(**request_init) # Mock the http request call within the method and fake a BadRequest error. @@ -3157,10 +4968,10 @@ def test_create_engine_rest_bad_request( response_value.status_code = 400 response_value.request = Request() req.return_value = response_value - client.create_engine(request) + client.get_engine(request) -def test_create_engine_rest_flattened(): +def test_get_engine_rest_flattened(): client = EngineServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", @@ -3169,48 +4980,42 @@ def test_create_engine_rest_flattened(): # 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") + return_value = engine.Engine() # get arguments that satisfy an http rule for this method sample_request = { - "parent": "projects/sample1/locations/sample2/collections/sample3" + "name": "projects/sample1/locations/sample2/collections/sample3/engines/sample4" } # get truthy value for each flattened field mock_args = dict( - parent="parent_value", - engine=gcd_engine.Engine( - chat_engine_config=gcd_engine.Engine.ChatEngineConfig( - agent_creation_config=gcd_engine.Engine.ChatEngineConfig.AgentCreationConfig( - business="business_value" - ) - ) - ), - engine_id="engine_id_value", + 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 = engine.Engine.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.create_engine(**mock_args) + client.get_engine(**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/v1beta/{parent=projects/*/locations/*/collections/*}/engines" + "%s/v1beta/{name=projects/*/locations/*/collections/*/engines/*}" % client.transport._host, args[1], ) -def test_create_engine_rest_flattened_error(transport: str = "rest"): +def test_get_engine_rest_flattened_error(transport: str = "rest"): client = EngineServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, @@ -3219,21 +5024,13 @@ def test_create_engine_rest_flattened_error(transport: str = "rest"): # Attempting to call a method with both a request object and flattened # fields is an error. with pytest.raises(ValueError): - client.create_engine( - engine_service.CreateEngineRequest(), - parent="parent_value", - engine=gcd_engine.Engine( - chat_engine_config=gcd_engine.Engine.ChatEngineConfig( - agent_creation_config=gcd_engine.Engine.ChatEngineConfig.AgentCreationConfig( - business="business_value" - ) - ) - ), - engine_id="engine_id_value", + client.get_engine( + engine_service.GetEngineRequest(), + name="name_value", ) -def test_create_engine_rest_error(): +def test_get_engine_rest_error(): client = EngineServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest" ) @@ -3242,47 +5039,50 @@ def test_create_engine_rest_error(): @pytest.mark.parametrize( "request_type", [ - engine_service.DeleteEngineRequest, + engine_service.ListEnginesRequest, dict, ], ) -def test_delete_engine_rest(request_type): +def test_list_engines_rest(request_type): client = EngineServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", ) # send a request that will satisfy transcoding - request_init = { - "name": "projects/sample1/locations/sample2/collections/sample3/engines/sample4" - } + request_init = {"parent": "projects/sample1/locations/sample2/collections/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") + return_value = engine_service.ListEnginesResponse( + next_page_token="next_page_token_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 = engine_service.ListEnginesResponse.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.delete_engine(request) + response = client.list_engines(request) # Establish that the response is the type that we expect. - assert response.operation.name == "operations/spam" + assert isinstance(response, pagers.ListEnginesPager) + assert response.next_page_token == "next_page_token_value" -def test_delete_engine_rest_required_fields( - request_type=engine_service.DeleteEngineRequest, +def test_list_engines_rest_required_fields( + request_type=engine_service.ListEnginesRequest, ): transport_class = transports.EngineServiceRestTransport request_init = {} - request_init["name"] = "" + request_init["parent"] = "" request = request_type(**request_init) pb_request = request_type.pb(request) jsonified_request = json.loads( @@ -3293,21 +5093,29 @@ def test_delete_engine_rest_required_fields( unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).delete_engine._get_unset_required_fields(jsonified_request) + ).list_engines._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" + jsonified_request["parent"] = "parent_value" unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).delete_engine._get_unset_required_fields(jsonified_request) + ).list_engines._get_unset_required_fields(jsonified_request) + # Check that path parameters and body parameters are not mixing in. + assert not set(unset_fields) - set( + ( + "filter", + "page_size", + "page_token", + ) + ) 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" + assert "parent" in jsonified_request + assert jsonified_request["parent"] == "parent_value" client = EngineServiceClient( credentials=ga_credentials.AnonymousCredentials(), @@ -3316,7 +5124,7 @@ def test_delete_engine_rest_required_fields( request = request_type(**request_init) # Designate an appropriate value for the returned response. - return_value = operations_pb2.Operation(name="operations/spam") + return_value = engine_service.ListEnginesResponse() # 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 @@ -3328,36 +5136,48 @@ def test_delete_engine_rest_required_fields( pb_request = request_type.pb(request) transcode_result = { "uri": "v1/sample_method", - "method": "delete", + "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 = engine_service.ListEnginesResponse.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.delete_engine(request) + response = client.list_engines(request) expected_params = [("$alt", "json;enum-encoding=int")] actual_params = req.call_args.kwargs["params"] assert expected_params == actual_params -def test_delete_engine_rest_unset_required_fields(): +def test_list_engines_rest_unset_required_fields(): transport = transports.EngineServiceRestTransport( credentials=ga_credentials.AnonymousCredentials ) - unset_fields = transport.delete_engine._get_unset_required_fields({}) - assert set(unset_fields) == (set(()) & set(("name",))) + unset_fields = transport.list_engines._get_unset_required_fields({}) + assert set(unset_fields) == ( + set( + ( + "filter", + "pageSize", + "pageToken", + ) + ) + & set(("parent",)) + ) @pytest.mark.parametrize("null_interceptor", [True, False]) -def test_delete_engine_rest_interceptors(null_interceptor): +def test_list_engines_rest_interceptors(null_interceptor): transport = transports.EngineServiceRestTransport( credentials=ga_credentials.AnonymousCredentials(), interceptor=None @@ -3370,16 +5190,14 @@ def test_delete_engine_rest_interceptors(null_interceptor): ) as req, mock.patch.object( path_template, "transcode" ) as transcode, mock.patch.object( - operation.Operation, "_set_result_from_operation" - ), mock.patch.object( - transports.EngineServiceRestInterceptor, "post_delete_engine" + transports.EngineServiceRestInterceptor, "post_list_engines" ) as post, mock.patch.object( - transports.EngineServiceRestInterceptor, "pre_delete_engine" + transports.EngineServiceRestInterceptor, "pre_list_engines" ) as pre: pre.assert_not_called() post.assert_not_called() - pb_message = engine_service.DeleteEngineRequest.pb( - engine_service.DeleteEngineRequest() + pb_message = engine_service.ListEnginesRequest.pb( + engine_service.ListEnginesRequest() ) transcode.return_value = { "method": "post", @@ -3391,19 +5209,19 @@ def test_delete_engine_rest_interceptors(null_interceptor): 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() + req.return_value._content = engine_service.ListEnginesResponse.to_json( + engine_service.ListEnginesResponse() ) - request = engine_service.DeleteEngineRequest() + request = engine_service.ListEnginesRequest() metadata = [ ("key", "val"), ("cephalopod", "squid"), ] pre.return_value = request, metadata - post.return_value = operations_pb2.Operation() + post.return_value = engine_service.ListEnginesResponse() - client.delete_engine( + client.list_engines( request, metadata=[ ("key", "val"), @@ -3415,8 +5233,8 @@ def test_delete_engine_rest_interceptors(null_interceptor): post.assert_called_once() -def test_delete_engine_rest_bad_request( - transport: str = "rest", request_type=engine_service.DeleteEngineRequest +def test_list_engines_rest_bad_request( + transport: str = "rest", request_type=engine_service.ListEnginesRequest ): client = EngineServiceClient( credentials=ga_credentials.AnonymousCredentials(), @@ -3424,9 +5242,7 @@ def test_delete_engine_rest_bad_request( ) # send a request that will satisfy transcoding - request_init = { - "name": "projects/sample1/locations/sample2/collections/sample3/engines/sample4" - } + request_init = {"parent": "projects/sample1/locations/sample2/collections/sample3"} request = request_type(**request_init) # Mock the http request call within the method and fake a BadRequest error. @@ -3438,10 +5254,10 @@ def test_delete_engine_rest_bad_request( response_value.status_code = 400 response_value.request = Request() req.return_value = response_value - client.delete_engine(request) + client.list_engines(request) -def test_delete_engine_rest_flattened(): +def test_list_engines_rest_flattened(): client = EngineServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", @@ -3450,40 +5266,42 @@ def test_delete_engine_rest_flattened(): # 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") + return_value = engine_service.ListEnginesResponse() # get arguments that satisfy an http rule for this method sample_request = { - "name": "projects/sample1/locations/sample2/collections/sample3/engines/sample4" + "parent": "projects/sample1/locations/sample2/collections/sample3" } # get truthy value for each flattened field mock_args = dict( - name="name_value", + 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 = engine_service.ListEnginesResponse.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.delete_engine(**mock_args) + client.list_engines(**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/v1beta/{name=projects/*/locations/*/collections/*/engines/*}" + "%s/v1beta/{parent=projects/*/locations/*/collections/*}/engines" % client.transport._host, args[1], ) -def test_delete_engine_rest_flattened_error(transport: str = "rest"): +def test_list_engines_rest_flattened_error(transport: str = "rest"): client = EngineServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, @@ -3492,26 +5310,85 @@ def test_delete_engine_rest_flattened_error(transport: str = "rest"): # Attempting to call a method with both a request object and flattened # fields is an error. with pytest.raises(ValueError): - client.delete_engine( - engine_service.DeleteEngineRequest(), - name="name_value", + client.list_engines( + engine_service.ListEnginesRequest(), + parent="parent_value", ) -def test_delete_engine_rest_error(): +def test_list_engines_rest_pager(transport: str = "rest"): client = EngineServiceClient( - credentials=ga_credentials.AnonymousCredentials(), transport="rest" + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, ) + # Mock the http request call within the method and fake a response. + with mock.patch.object(Session, "request") as req: + # TODO(kbandes): remove this mock unless there's a good reason for it. + # with mock.patch.object(path_template, 'transcode') as transcode: + # Set the response as a series of pages + response = ( + engine_service.ListEnginesResponse( + engines=[ + engine.Engine(), + engine.Engine(), + engine.Engine(), + ], + next_page_token="abc", + ), + engine_service.ListEnginesResponse( + engines=[], + next_page_token="def", + ), + engine_service.ListEnginesResponse( + engines=[ + engine.Engine(), + ], + next_page_token="ghi", + ), + engine_service.ListEnginesResponse( + engines=[ + engine.Engine(), + engine.Engine(), + ], + ), + ) + # Two responses for two calls + response = response + response + + # Wrap the values into proper Response objs + response = tuple( + engine_service.ListEnginesResponse.to_json(x) for x in response + ) + return_values = tuple(Response() for i in response) + for return_val, response_val in zip(return_values, response): + return_val._content = response_val.encode("UTF-8") + return_val.status_code = 200 + req.side_effect = return_values + + sample_request = { + "parent": "projects/sample1/locations/sample2/collections/sample3" + } + + pager = client.list_engines(request=sample_request) + + results = list(pager) + assert len(results) == 6 + assert all(isinstance(i, engine.Engine) for i in results) + + pages = list(client.list_engines(request=sample_request).pages) + for page_, token in zip(pages, ["abc", "def", "ghi", ""]): + assert page_.raw_page.next_page_token == token + @pytest.mark.parametrize( "request_type", [ - engine_service.UpdateEngineRequest, + engine_service.PauseEngineRequest, dict, ], ) -def test_update_engine_rest(request_type): +def test_pause_engine_rest(request_type): client = EngineServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", @@ -3519,104 +5396,14 @@ def test_update_engine_rest(request_type): # send a request that will satisfy transcoding request_init = { - "engine": { - "name": "projects/sample1/locations/sample2/collections/sample3/engines/sample4" - } - } - request_init["engine"] = { - "chat_engine_config": { - "agent_creation_config": { - "business": "business_value", - "default_language_code": "default_language_code_value", - "time_zone": "time_zone_value", - "location": "location_value", - }, - "dialogflow_agent_to_link": "dialogflow_agent_to_link_value", - }, - "search_engine_config": {"search_tier": 1, "search_add_ons": [1]}, - "chat_engine_metadata": {"dialogflow_agent": "dialogflow_agent_value"}, - "name": "projects/sample1/locations/sample2/collections/sample3/engines/sample4", - "display_name": "display_name_value", - "create_time": {"seconds": 751, "nanos": 543}, - "update_time": {}, - "data_store_ids": ["data_store_ids_value1", "data_store_ids_value2"], - "solution_type": 1, - "industry_vertical": 1, - "common_config": {"company_name": "company_name_value"}, + "name": "projects/sample1/locations/sample2/collections/sample3/engines/sample4" } - # 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 = engine_service.UpdateEngineRequest.meta.fields["engine"] - - 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["engine"].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["engine"][field])): - del request_init["engine"][field][i][subfield] - else: - del request_init["engine"][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 = gcd_engine.Engine( + return_value = engine.Engine( name="name_value", display_name="display_name_value", data_store_ids=["data_store_ids_value"], @@ -3628,15 +5415,15 @@ def get_message_fields(field): response_value = Response() response_value.status_code = 200 # Convert return value to protobuf type - return_value = gcd_engine.Engine.pb(return_value) + return_value = engine.Engine.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_engine(request) + response = client.pause_engine(request) # Establish that the response is the type that we expect. - assert isinstance(response, gcd_engine.Engine) + assert isinstance(response, engine.Engine) assert response.name == "name_value" assert response.display_name == "display_name_value" assert response.data_store_ids == ["data_store_ids_value"] @@ -3644,12 +5431,13 @@ def get_message_fields(field): assert response.industry_vertical == common.IndustryVertical.GENERIC -def test_update_engine_rest_required_fields( - request_type=engine_service.UpdateEngineRequest, +def test_pause_engine_rest_required_fields( + request_type=engine_service.PauseEngineRequest, ): transport_class = transports.EngineServiceRestTransport request_init = {} + request_init["name"] = "" request = request_type(**request_init) pb_request = request_type.pb(request) jsonified_request = json.loads( @@ -3660,19 +5448,21 @@ def test_update_engine_rest_required_fields( unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).update_engine._get_unset_required_fields(jsonified_request) + ).pause_engine._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() - ).update_engine._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",)) + credentials=ga_credentials.AnonymousCredentials() + ).pause_engine._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 = EngineServiceClient( credentials=ga_credentials.AnonymousCredentials(), @@ -3681,7 +5471,7 @@ def test_update_engine_rest_required_fields( request = request_type(**request_init) # Designate an appropriate value for the returned response. - return_value = gcd_engine.Engine() + return_value = engine.Engine() # 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 @@ -3693,7 +5483,7 @@ def test_update_engine_rest_required_fields( pb_request = request_type.pb(request) transcode_result = { "uri": "v1/sample_method", - "method": "patch", + "method": "post", "query_params": pb_request, } transcode_result["body"] = pb_request @@ -3703,30 +5493,30 @@ def test_update_engine_rest_required_fields( response_value.status_code = 200 # Convert return value to protobuf type - return_value = gcd_engine.Engine.pb(return_value) + return_value = engine.Engine.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_engine(request) + response = client.pause_engine(request) expected_params = [("$alt", "json;enum-encoding=int")] actual_params = req.call_args.kwargs["params"] assert expected_params == actual_params -def test_update_engine_rest_unset_required_fields(): +def test_pause_engine_rest_unset_required_fields(): transport = transports.EngineServiceRestTransport( credentials=ga_credentials.AnonymousCredentials ) - unset_fields = transport.update_engine._get_unset_required_fields({}) - assert set(unset_fields) == (set(("updateMask",)) & set(("engine",))) + unset_fields = transport.pause_engine._get_unset_required_fields({}) + assert set(unset_fields) == (set(()) & set(("name",))) @pytest.mark.parametrize("null_interceptor", [True, False]) -def test_update_engine_rest_interceptors(null_interceptor): +def test_pause_engine_rest_interceptors(null_interceptor): transport = transports.EngineServiceRestTransport( credentials=ga_credentials.AnonymousCredentials(), interceptor=None @@ -3739,14 +5529,14 @@ def test_update_engine_rest_interceptors(null_interceptor): ) as req, mock.patch.object( path_template, "transcode" ) as transcode, mock.patch.object( - transports.EngineServiceRestInterceptor, "post_update_engine" + transports.EngineServiceRestInterceptor, "post_pause_engine" ) as post, mock.patch.object( - transports.EngineServiceRestInterceptor, "pre_update_engine" + transports.EngineServiceRestInterceptor, "pre_pause_engine" ) as pre: pre.assert_not_called() post.assert_not_called() - pb_message = engine_service.UpdateEngineRequest.pb( - engine_service.UpdateEngineRequest() + pb_message = engine_service.PauseEngineRequest.pb( + engine_service.PauseEngineRequest() ) transcode.return_value = { "method": "post", @@ -3758,17 +5548,17 @@ def test_update_engine_rest_interceptors(null_interceptor): req.return_value = Response() req.return_value.status_code = 200 req.return_value.request = PreparedRequest() - req.return_value._content = gcd_engine.Engine.to_json(gcd_engine.Engine()) + req.return_value._content = engine.Engine.to_json(engine.Engine()) - request = engine_service.UpdateEngineRequest() + request = engine_service.PauseEngineRequest() metadata = [ ("key", "val"), ("cephalopod", "squid"), ] pre.return_value = request, metadata - post.return_value = gcd_engine.Engine() + post.return_value = engine.Engine() - client.update_engine( + client.pause_engine( request, metadata=[ ("key", "val"), @@ -3780,8 +5570,8 @@ def test_update_engine_rest_interceptors(null_interceptor): post.assert_called_once() -def test_update_engine_rest_bad_request( - transport: str = "rest", request_type=engine_service.UpdateEngineRequest +def test_pause_engine_rest_bad_request( + transport: str = "rest", request_type=engine_service.PauseEngineRequest ): client = EngineServiceClient( credentials=ga_credentials.AnonymousCredentials(), @@ -3790,9 +5580,7 @@ def test_update_engine_rest_bad_request( # send a request that will satisfy transcoding request_init = { - "engine": { - "name": "projects/sample1/locations/sample2/collections/sample3/engines/sample4" - } + "name": "projects/sample1/locations/sample2/collections/sample3/engines/sample4" } request = request_type(**request_init) @@ -3805,10 +5593,10 @@ def test_update_engine_rest_bad_request( response_value.status_code = 400 response_value.request = Request() req.return_value = response_value - client.update_engine(request) + client.pause_engine(request) -def test_update_engine_rest_flattened(): +def test_pause_engine_rest_flattened(): client = EngineServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", @@ -3817,25 +5605,16 @@ def test_update_engine_rest_flattened(): # 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 = gcd_engine.Engine() + return_value = engine.Engine() # get arguments that satisfy an http rule for this method sample_request = { - "engine": { - "name": "projects/sample1/locations/sample2/collections/sample3/engines/sample4" - } + "name": "projects/sample1/locations/sample2/collections/sample3/engines/sample4" } # get truthy value for each flattened field mock_args = dict( - engine=gcd_engine.Engine( - chat_engine_config=gcd_engine.Engine.ChatEngineConfig( - agent_creation_config=gcd_engine.Engine.ChatEngineConfig.AgentCreationConfig( - business="business_value" - ) - ) - ), - update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + name="name_value", ) mock_args.update(sample_request) @@ -3843,25 +5622,25 @@ def test_update_engine_rest_flattened(): response_value = Response() response_value.status_code = 200 # Convert return value to protobuf type - return_value = gcd_engine.Engine.pb(return_value) + return_value = engine.Engine.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_engine(**mock_args) + client.pause_engine(**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/v1beta/{engine.name=projects/*/locations/*/collections/*/engines/*}" + "%s/v1beta/{name=projects/*/locations/*/collections/*/engines/*}:pause" % client.transport._host, args[1], ) -def test_update_engine_rest_flattened_error(transport: str = "rest"): +def test_pause_engine_rest_flattened_error(transport: str = "rest"): client = EngineServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, @@ -3870,20 +5649,13 @@ def test_update_engine_rest_flattened_error(transport: str = "rest"): # Attempting to call a method with both a request object and flattened # fields is an error. with pytest.raises(ValueError): - client.update_engine( - engine_service.UpdateEngineRequest(), - engine=gcd_engine.Engine( - chat_engine_config=gcd_engine.Engine.ChatEngineConfig( - agent_creation_config=gcd_engine.Engine.ChatEngineConfig.AgentCreationConfig( - business="business_value" - ) - ) - ), - update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + client.pause_engine( + engine_service.PauseEngineRequest(), + name="name_value", ) -def test_update_engine_rest_error(): +def test_pause_engine_rest_error(): client = EngineServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest" ) @@ -3892,11 +5664,11 @@ def test_update_engine_rest_error(): @pytest.mark.parametrize( "request_type", [ - engine_service.GetEngineRequest, + engine_service.ResumeEngineRequest, dict, ], ) -def test_get_engine_rest(request_type): +def test_resume_engine_rest(request_type): client = EngineServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", @@ -3928,7 +5700,7 @@ def test_get_engine_rest(request_type): response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - response = client.get_engine(request) + response = client.resume_engine(request) # Establish that the response is the type that we expect. assert isinstance(response, engine.Engine) @@ -3939,7 +5711,9 @@ def test_get_engine_rest(request_type): assert response.industry_vertical == common.IndustryVertical.GENERIC -def test_get_engine_rest_required_fields(request_type=engine_service.GetEngineRequest): +def test_resume_engine_rest_required_fields( + request_type=engine_service.ResumeEngineRequest, +): transport_class = transports.EngineServiceRestTransport request_init = {} @@ -3954,7 +5728,7 @@ def test_get_engine_rest_required_fields(request_type=engine_service.GetEngineRe unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).get_engine._get_unset_required_fields(jsonified_request) + ).resume_engine._get_unset_required_fields(jsonified_request) jsonified_request.update(unset_fields) # verify required fields with default values are now present @@ -3963,7 +5737,7 @@ def test_get_engine_rest_required_fields(request_type=engine_service.GetEngineRe unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).get_engine._get_unset_required_fields(jsonified_request) + ).resume_engine._get_unset_required_fields(jsonified_request) jsonified_request.update(unset_fields) # verify required fields with non-default values are left alone @@ -3989,9 +5763,10 @@ def test_get_engine_rest_required_fields(request_type=engine_service.GetEngineRe pb_request = request_type.pb(request) transcode_result = { "uri": "v1/sample_method", - "method": "get", + "method": "post", "query_params": pb_request, } + transcode_result["body"] = pb_request transcode.return_value = transcode_result response_value = Response() @@ -4004,24 +5779,24 @@ def test_get_engine_rest_required_fields(request_type=engine_service.GetEngineRe response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - response = client.get_engine(request) + response = client.resume_engine(request) expected_params = [("$alt", "json;enum-encoding=int")] actual_params = req.call_args.kwargs["params"] assert expected_params == actual_params -def test_get_engine_rest_unset_required_fields(): +def test_resume_engine_rest_unset_required_fields(): transport = transports.EngineServiceRestTransport( credentials=ga_credentials.AnonymousCredentials ) - unset_fields = transport.get_engine._get_unset_required_fields({}) + unset_fields = transport.resume_engine._get_unset_required_fields({}) assert set(unset_fields) == (set(()) & set(("name",))) @pytest.mark.parametrize("null_interceptor", [True, False]) -def test_get_engine_rest_interceptors(null_interceptor): +def test_resume_engine_rest_interceptors(null_interceptor): transport = transports.EngineServiceRestTransport( credentials=ga_credentials.AnonymousCredentials(), interceptor=None @@ -4034,14 +5809,14 @@ def test_get_engine_rest_interceptors(null_interceptor): ) as req, mock.patch.object( path_template, "transcode" ) as transcode, mock.patch.object( - transports.EngineServiceRestInterceptor, "post_get_engine" + transports.EngineServiceRestInterceptor, "post_resume_engine" ) as post, mock.patch.object( - transports.EngineServiceRestInterceptor, "pre_get_engine" + transports.EngineServiceRestInterceptor, "pre_resume_engine" ) as pre: pre.assert_not_called() post.assert_not_called() - pb_message = engine_service.GetEngineRequest.pb( - engine_service.GetEngineRequest() + pb_message = engine_service.ResumeEngineRequest.pb( + engine_service.ResumeEngineRequest() ) transcode.return_value = { "method": "post", @@ -4055,7 +5830,7 @@ def test_get_engine_rest_interceptors(null_interceptor): req.return_value.request = PreparedRequest() req.return_value._content = engine.Engine.to_json(engine.Engine()) - request = engine_service.GetEngineRequest() + request = engine_service.ResumeEngineRequest() metadata = [ ("key", "val"), ("cephalopod", "squid"), @@ -4063,7 +5838,7 @@ def test_get_engine_rest_interceptors(null_interceptor): pre.return_value = request, metadata post.return_value = engine.Engine() - client.get_engine( + client.resume_engine( request, metadata=[ ("key", "val"), @@ -4075,8 +5850,8 @@ def test_get_engine_rest_interceptors(null_interceptor): post.assert_called_once() -def test_get_engine_rest_bad_request( - transport: str = "rest", request_type=engine_service.GetEngineRequest +def test_resume_engine_rest_bad_request( + transport: str = "rest", request_type=engine_service.ResumeEngineRequest ): client = EngineServiceClient( credentials=ga_credentials.AnonymousCredentials(), @@ -4098,10 +5873,10 @@ def test_get_engine_rest_bad_request( response_value.status_code = 400 response_value.request = Request() req.return_value = response_value - client.get_engine(request) + client.resume_engine(request) -def test_get_engine_rest_flattened(): +def test_resume_engine_rest_flattened(): client = EngineServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", @@ -4132,20 +5907,20 @@ def test_get_engine_rest_flattened(): response_value._content = json_return_value.encode("UTF-8") req.return_value = response_value - client.get_engine(**mock_args) + client.resume_engine(**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/v1beta/{name=projects/*/locations/*/collections/*/engines/*}" + "%s/v1beta/{name=projects/*/locations/*/collections/*/engines/*}:resume" % client.transport._host, args[1], ) -def test_get_engine_rest_flattened_error(transport: str = "rest"): +def test_resume_engine_rest_flattened_error(transport: str = "rest"): client = EngineServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, @@ -4154,13 +5929,13 @@ def test_get_engine_rest_flattened_error(transport: str = "rest"): # Attempting to call a method with both a request object and flattened # fields is an error. with pytest.raises(ValueError): - client.get_engine( - engine_service.GetEngineRequest(), + client.resume_engine( + engine_service.ResumeEngineRequest(), name="name_value", ) -def test_get_engine_rest_error(): +def test_resume_engine_rest_error(): client = EngineServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest" ) @@ -4169,50 +5944,47 @@ def test_get_engine_rest_error(): @pytest.mark.parametrize( "request_type", [ - engine_service.ListEnginesRequest, + engine_service.TuneEngineRequest, dict, ], ) -def test_list_engines_rest(request_type): +def test_tune_engine_rest(request_type): client = EngineServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", ) # send a request that will satisfy transcoding - request_init = {"parent": "projects/sample1/locations/sample2/collections/sample3"} + request_init = { + "name": "projects/sample1/locations/sample2/collections/sample3/engines/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 = engine_service.ListEnginesResponse( - next_page_token="next_page_token_value", - ) + return_value = operations_pb2.Operation(name="operations/spam") # Wrap the value into a proper Response obj response_value = Response() response_value.status_code = 200 - # Convert return value to protobuf type - return_value = engine_service.ListEnginesResponse.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_engines(request) + response = client.tune_engine(request) # Establish that the response is the type that we expect. - assert isinstance(response, pagers.ListEnginesPager) - assert response.next_page_token == "next_page_token_value" + assert response.operation.name == "operations/spam" -def test_list_engines_rest_required_fields( - request_type=engine_service.ListEnginesRequest, +def test_tune_engine_rest_required_fields( + request_type=engine_service.TuneEngineRequest, ): transport_class = transports.EngineServiceRestTransport request_init = {} - request_init["parent"] = "" + request_init["name"] = "" request = request_type(**request_init) pb_request = request_type.pb(request) jsonified_request = json.loads( @@ -4223,29 +5995,21 @@ def test_list_engines_rest_required_fields( unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).list_engines._get_unset_required_fields(jsonified_request) + ).tune_engine._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" + jsonified_request["name"] = "name_value" unset_fields = transport_class( credentials=ga_credentials.AnonymousCredentials() - ).list_engines._get_unset_required_fields(jsonified_request) - # Check that path parameters and body parameters are not mixing in. - assert not set(unset_fields) - set( - ( - "filter", - "page_size", - "page_token", - ) - ) + ).tune_engine._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" + assert "name" in jsonified_request + assert jsonified_request["name"] == "name_value" client = EngineServiceClient( credentials=ga_credentials.AnonymousCredentials(), @@ -4254,7 +6018,7 @@ def test_list_engines_rest_required_fields( request = request_type(**request_init) # Designate an appropriate value for the returned response. - return_value = engine_service.ListEnginesResponse() + 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 @@ -4266,48 +6030,37 @@ def test_list_engines_rest_required_fields( pb_request = request_type.pb(request) transcode_result = { "uri": "v1/sample_method", - "method": "get", + "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 = engine_service.ListEnginesResponse.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_engines(request) + response = client.tune_engine(request) expected_params = [("$alt", "json;enum-encoding=int")] actual_params = req.call_args.kwargs["params"] assert expected_params == actual_params -def test_list_engines_rest_unset_required_fields(): +def test_tune_engine_rest_unset_required_fields(): transport = transports.EngineServiceRestTransport( credentials=ga_credentials.AnonymousCredentials ) - unset_fields = transport.list_engines._get_unset_required_fields({}) - assert set(unset_fields) == ( - set( - ( - "filter", - "pageSize", - "pageToken", - ) - ) - & set(("parent",)) - ) + unset_fields = transport.tune_engine._get_unset_required_fields({}) + assert set(unset_fields) == (set(()) & set(("name",))) @pytest.mark.parametrize("null_interceptor", [True, False]) -def test_list_engines_rest_interceptors(null_interceptor): +def test_tune_engine_rest_interceptors(null_interceptor): transport = transports.EngineServiceRestTransport( credentials=ga_credentials.AnonymousCredentials(), interceptor=None @@ -4320,14 +6073,16 @@ def test_list_engines_rest_interceptors(null_interceptor): ) as req, mock.patch.object( path_template, "transcode" ) as transcode, mock.patch.object( - transports.EngineServiceRestInterceptor, "post_list_engines" + operation.Operation, "_set_result_from_operation" + ), mock.patch.object( + transports.EngineServiceRestInterceptor, "post_tune_engine" ) as post, mock.patch.object( - transports.EngineServiceRestInterceptor, "pre_list_engines" + transports.EngineServiceRestInterceptor, "pre_tune_engine" ) as pre: pre.assert_not_called() post.assert_not_called() - pb_message = engine_service.ListEnginesRequest.pb( - engine_service.ListEnginesRequest() + pb_message = engine_service.TuneEngineRequest.pb( + engine_service.TuneEngineRequest() ) transcode.return_value = { "method": "post", @@ -4339,19 +6094,19 @@ def test_list_engines_rest_interceptors(null_interceptor): req.return_value = Response() req.return_value.status_code = 200 req.return_value.request = PreparedRequest() - req.return_value._content = engine_service.ListEnginesResponse.to_json( - engine_service.ListEnginesResponse() + req.return_value._content = json_format.MessageToJson( + operations_pb2.Operation() ) - request = engine_service.ListEnginesRequest() + request = engine_service.TuneEngineRequest() metadata = [ ("key", "val"), ("cephalopod", "squid"), ] pre.return_value = request, metadata - post.return_value = engine_service.ListEnginesResponse() + post.return_value = operations_pb2.Operation() - client.list_engines( + client.tune_engine( request, metadata=[ ("key", "val"), @@ -4363,8 +6118,8 @@ def test_list_engines_rest_interceptors(null_interceptor): post.assert_called_once() -def test_list_engines_rest_bad_request( - transport: str = "rest", request_type=engine_service.ListEnginesRequest +def test_tune_engine_rest_bad_request( + transport: str = "rest", request_type=engine_service.TuneEngineRequest ): client = EngineServiceClient( credentials=ga_credentials.AnonymousCredentials(), @@ -4372,7 +6127,9 @@ def test_list_engines_rest_bad_request( ) # send a request that will satisfy transcoding - request_init = {"parent": "projects/sample1/locations/sample2/collections/sample3"} + request_init = { + "name": "projects/sample1/locations/sample2/collections/sample3/engines/sample4" + } request = request_type(**request_init) # Mock the http request call within the method and fake a BadRequest error. @@ -4384,10 +6141,10 @@ def test_list_engines_rest_bad_request( response_value.status_code = 400 response_value.request = Request() req.return_value = response_value - client.list_engines(request) + client.tune_engine(request) -def test_list_engines_rest_flattened(): +def test_tune_engine_rest_flattened(): client = EngineServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", @@ -4396,42 +6153,40 @@ def test_list_engines_rest_flattened(): # 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 = engine_service.ListEnginesResponse() + return_value = operations_pb2.Operation(name="operations/spam") # get arguments that satisfy an http rule for this method sample_request = { - "parent": "projects/sample1/locations/sample2/collections/sample3" + "name": "projects/sample1/locations/sample2/collections/sample3/engines/sample4" } # get truthy value for each flattened field mock_args = dict( - parent="parent_value", + 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 = engine_service.ListEnginesResponse.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_engines(**mock_args) + client.tune_engine(**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/v1beta/{parent=projects/*/locations/*/collections/*}/engines" + "%s/v1beta/{name=projects/*/locations/*/collections/*/engines/*}:tune" % client.transport._host, args[1], ) -def test_list_engines_rest_flattened_error(transport: str = "rest"): +def test_tune_engine_rest_flattened_error(transport: str = "rest"): client = EngineServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, @@ -4440,76 +6195,17 @@ def test_list_engines_rest_flattened_error(transport: str = "rest"): # Attempting to call a method with both a request object and flattened # fields is an error. with pytest.raises(ValueError): - client.list_engines( - engine_service.ListEnginesRequest(), - parent="parent_value", + client.tune_engine( + engine_service.TuneEngineRequest(), + name="name_value", ) -def test_list_engines_rest_pager(transport: str = "rest"): +def test_tune_engine_rest_error(): client = EngineServiceClient( - credentials=ga_credentials.AnonymousCredentials(), - transport=transport, + credentials=ga_credentials.AnonymousCredentials(), transport="rest" ) - # Mock the http request call within the method and fake a response. - with mock.patch.object(Session, "request") as req: - # TODO(kbandes): remove this mock unless there's a good reason for it. - # with mock.patch.object(path_template, 'transcode') as transcode: - # Set the response as a series of pages - response = ( - engine_service.ListEnginesResponse( - engines=[ - engine.Engine(), - engine.Engine(), - engine.Engine(), - ], - next_page_token="abc", - ), - engine_service.ListEnginesResponse( - engines=[], - next_page_token="def", - ), - engine_service.ListEnginesResponse( - engines=[ - engine.Engine(), - ], - next_page_token="ghi", - ), - engine_service.ListEnginesResponse( - engines=[ - engine.Engine(), - engine.Engine(), - ], - ), - ) - # Two responses for two calls - response = response + response - - # Wrap the values into proper Response objs - response = tuple( - engine_service.ListEnginesResponse.to_json(x) for x in response - ) - return_values = tuple(Response() for i in response) - for return_val, response_val in zip(return_values, response): - return_val._content = response_val.encode("UTF-8") - return_val.status_code = 200 - req.side_effect = return_values - - sample_request = { - "parent": "projects/sample1/locations/sample2/collections/sample3" - } - - pager = client.list_engines(request=sample_request) - - results = list(pager) - assert len(results) == 6 - assert all(isinstance(i, engine.Engine) for i in results) - - pages = list(client.list_engines(request=sample_request).pages) - for page_, token in zip(pages, ["abc", "def", "ghi", ""]): - assert page_.raw_page.next_page_token == token - def test_credentials_transport_error(): # It is an error to provide credentials and a transport instance. @@ -4655,6 +6351,9 @@ def test_engine_service_base_transport(): "update_engine", "get_engine", "list_engines", + "pause_engine", + "resume_engine", + "tune_engine", "get_operation", "list_operations", ) @@ -4952,6 +6651,15 @@ def test_engine_service_client_transport_session_collision(transport_name): session1 = client1.transport.list_engines._session session2 = client2.transport.list_engines._session assert session1 != session2 + session1 = client1.transport.pause_engine._session + session2 = client2.transport.pause_engine._session + assert session1 != session2 + session1 = client1.transport.resume_engine._session + session2 = client2.transport.resume_engine._session + assert session1 != session2 + session1 = client1.transport.tune_engine._session + session2 = client2.transport.tune_engine._session + assert session1 != session2 def test_engine_service_grpc_transport_channel(): diff --git a/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1beta/test_grounded_generation_service.py b/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1beta/test_grounded_generation_service.py new file mode 100644 index 000000000000..13286305663b --- /dev/null +++ b/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1beta/test_grounded_generation_service.py @@ -0,0 +1,2824 @@ +# -*- 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 +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 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.discoveryengine_v1beta.services.grounded_generation_service import ( + GroundedGenerationServiceAsyncClient, + GroundedGenerationServiceClient, + transports, +) +from google.cloud.discoveryengine_v1beta.types import ( + grounded_generation_service, + grounding, +) + + +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 GroundedGenerationServiceClient._get_default_mtls_endpoint(None) is None + assert ( + GroundedGenerationServiceClient._get_default_mtls_endpoint(api_endpoint) + == api_mtls_endpoint + ) + assert ( + GroundedGenerationServiceClient._get_default_mtls_endpoint(api_mtls_endpoint) + == api_mtls_endpoint + ) + assert ( + GroundedGenerationServiceClient._get_default_mtls_endpoint(sandbox_endpoint) + == sandbox_mtls_endpoint + ) + assert ( + GroundedGenerationServiceClient._get_default_mtls_endpoint( + sandbox_mtls_endpoint + ) + == sandbox_mtls_endpoint + ) + assert ( + GroundedGenerationServiceClient._get_default_mtls_endpoint(non_googleapi) + == non_googleapi + ) + + +def test__read_environment_variables(): + assert GroundedGenerationServiceClient._read_environment_variables() == ( + False, + "auto", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "true"}): + assert GroundedGenerationServiceClient._read_environment_variables() == ( + True, + "auto", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "false"}): + assert GroundedGenerationServiceClient._read_environment_variables() == ( + False, + "auto", + None, + ) + + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"} + ): + with pytest.raises(ValueError) as excinfo: + GroundedGenerationServiceClient._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 GroundedGenerationServiceClient._read_environment_variables() == ( + False, + "never", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): + assert GroundedGenerationServiceClient._read_environment_variables() == ( + False, + "always", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "auto"}): + assert GroundedGenerationServiceClient._read_environment_variables() == ( + False, + "auto", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "Unsupported"}): + with pytest.raises(MutualTLSChannelError) as excinfo: + GroundedGenerationServiceClient._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 GroundedGenerationServiceClient._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 GroundedGenerationServiceClient._get_client_cert_source(None, False) is None + assert ( + GroundedGenerationServiceClient._get_client_cert_source( + mock_provided_cert_source, False + ) + is None + ) + assert ( + GroundedGenerationServiceClient._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 ( + GroundedGenerationServiceClient._get_client_cert_source(None, True) + is mock_default_cert_source + ) + assert ( + GroundedGenerationServiceClient._get_client_cert_source( + mock_provided_cert_source, "true" + ) + is mock_provided_cert_source + ) + + +@mock.patch.object( + GroundedGenerationServiceClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(GroundedGenerationServiceClient), +) +@mock.patch.object( + GroundedGenerationServiceAsyncClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(GroundedGenerationServiceAsyncClient), +) +def test__get_api_endpoint(): + api_override = "foo.com" + mock_client_cert_source = mock.Mock() + default_universe = GroundedGenerationServiceClient._DEFAULT_UNIVERSE + default_endpoint = ( + GroundedGenerationServiceClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=default_universe + ) + ) + mock_universe = "bar.com" + mock_endpoint = GroundedGenerationServiceClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=mock_universe + ) + + assert ( + GroundedGenerationServiceClient._get_api_endpoint( + api_override, mock_client_cert_source, default_universe, "always" + ) + == api_override + ) + assert ( + GroundedGenerationServiceClient._get_api_endpoint( + None, mock_client_cert_source, default_universe, "auto" + ) + == GroundedGenerationServiceClient.DEFAULT_MTLS_ENDPOINT + ) + assert ( + GroundedGenerationServiceClient._get_api_endpoint( + None, None, default_universe, "auto" + ) + == default_endpoint + ) + assert ( + GroundedGenerationServiceClient._get_api_endpoint( + None, None, default_universe, "always" + ) + == GroundedGenerationServiceClient.DEFAULT_MTLS_ENDPOINT + ) + assert ( + GroundedGenerationServiceClient._get_api_endpoint( + None, mock_client_cert_source, default_universe, "always" + ) + == GroundedGenerationServiceClient.DEFAULT_MTLS_ENDPOINT + ) + assert ( + GroundedGenerationServiceClient._get_api_endpoint( + None, None, mock_universe, "never" + ) + == mock_endpoint + ) + assert ( + GroundedGenerationServiceClient._get_api_endpoint( + None, None, default_universe, "never" + ) + == default_endpoint + ) + + with pytest.raises(MutualTLSChannelError) as excinfo: + GroundedGenerationServiceClient._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 ( + GroundedGenerationServiceClient._get_universe_domain( + client_universe_domain, universe_domain_env + ) + == client_universe_domain + ) + assert ( + GroundedGenerationServiceClient._get_universe_domain(None, universe_domain_env) + == universe_domain_env + ) + assert ( + GroundedGenerationServiceClient._get_universe_domain(None, None) + == GroundedGenerationServiceClient._DEFAULT_UNIVERSE + ) + + with pytest.raises(ValueError) as excinfo: + GroundedGenerationServiceClient._get_universe_domain("", None) + assert str(excinfo.value) == "Universe Domain cannot be an empty string." + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name", + [ + ( + GroundedGenerationServiceClient, + transports.GroundedGenerationServiceGrpcTransport, + "grpc", + ), + ( + GroundedGenerationServiceClient, + transports.GroundedGenerationServiceRestTransport, + "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", + [ + (GroundedGenerationServiceClient, "grpc"), + (GroundedGenerationServiceAsyncClient, "grpc_asyncio"), + (GroundedGenerationServiceClient, "rest"), + ], +) +def test_grounded_generation_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 == ( + "discoveryengine.googleapis.com:443" + if transport_name in ["grpc", "grpc_asyncio"] + else "https://discoveryengine.googleapis.com" + ) + + +@pytest.mark.parametrize( + "transport_class,transport_name", + [ + (transports.GroundedGenerationServiceGrpcTransport, "grpc"), + (transports.GroundedGenerationServiceGrpcAsyncIOTransport, "grpc_asyncio"), + (transports.GroundedGenerationServiceRestTransport, "rest"), + ], +) +def test_grounded_generation_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", + [ + (GroundedGenerationServiceClient, "grpc"), + (GroundedGenerationServiceAsyncClient, "grpc_asyncio"), + (GroundedGenerationServiceClient, "rest"), + ], +) +def test_grounded_generation_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 == ( + "discoveryengine.googleapis.com:443" + if transport_name in ["grpc", "grpc_asyncio"] + else "https://discoveryengine.googleapis.com" + ) + + +def test_grounded_generation_service_client_get_transport_class(): + transport = GroundedGenerationServiceClient.get_transport_class() + available_transports = [ + transports.GroundedGenerationServiceGrpcTransport, + transports.GroundedGenerationServiceRestTransport, + ] + assert transport in available_transports + + transport = GroundedGenerationServiceClient.get_transport_class("grpc") + assert transport == transports.GroundedGenerationServiceGrpcTransport + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name", + [ + ( + GroundedGenerationServiceClient, + transports.GroundedGenerationServiceGrpcTransport, + "grpc", + ), + ( + GroundedGenerationServiceAsyncClient, + transports.GroundedGenerationServiceGrpcAsyncIOTransport, + "grpc_asyncio", + ), + ( + GroundedGenerationServiceClient, + transports.GroundedGenerationServiceRestTransport, + "rest", + ), + ], +) +@mock.patch.object( + GroundedGenerationServiceClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(GroundedGenerationServiceClient), +) +@mock.patch.object( + GroundedGenerationServiceAsyncClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(GroundedGenerationServiceAsyncClient), +) +def test_grounded_generation_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( + GroundedGenerationServiceClient, "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( + GroundedGenerationServiceClient, "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", + [ + ( + GroundedGenerationServiceClient, + transports.GroundedGenerationServiceGrpcTransport, + "grpc", + "true", + ), + ( + GroundedGenerationServiceAsyncClient, + transports.GroundedGenerationServiceGrpcAsyncIOTransport, + "grpc_asyncio", + "true", + ), + ( + GroundedGenerationServiceClient, + transports.GroundedGenerationServiceGrpcTransport, + "grpc", + "false", + ), + ( + GroundedGenerationServiceAsyncClient, + transports.GroundedGenerationServiceGrpcAsyncIOTransport, + "grpc_asyncio", + "false", + ), + ( + GroundedGenerationServiceClient, + transports.GroundedGenerationServiceRestTransport, + "rest", + "true", + ), + ( + GroundedGenerationServiceClient, + transports.GroundedGenerationServiceRestTransport, + "rest", + "false", + ), + ], +) +@mock.patch.object( + GroundedGenerationServiceClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(GroundedGenerationServiceClient), +) +@mock.patch.object( + GroundedGenerationServiceAsyncClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(GroundedGenerationServiceAsyncClient), +) +@mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "auto"}) +def test_grounded_generation_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", + [GroundedGenerationServiceClient, GroundedGenerationServiceAsyncClient], +) +@mock.patch.object( + GroundedGenerationServiceClient, + "DEFAULT_ENDPOINT", + modify_default_endpoint(GroundedGenerationServiceClient), +) +@mock.patch.object( + GroundedGenerationServiceAsyncClient, + "DEFAULT_ENDPOINT", + modify_default_endpoint(GroundedGenerationServiceAsyncClient), +) +def test_grounded_generation_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", + [GroundedGenerationServiceClient, GroundedGenerationServiceAsyncClient], +) +@mock.patch.object( + GroundedGenerationServiceClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(GroundedGenerationServiceClient), +) +@mock.patch.object( + GroundedGenerationServiceAsyncClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(GroundedGenerationServiceAsyncClient), +) +def test_grounded_generation_service_client_client_api_endpoint(client_class): + mock_client_cert_source = client_cert_source_callback + api_override = "foo.com" + default_universe = GroundedGenerationServiceClient._DEFAULT_UNIVERSE + default_endpoint = ( + GroundedGenerationServiceClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=default_universe + ) + ) + mock_universe = "bar.com" + mock_endpoint = GroundedGenerationServiceClient._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", + [ + ( + GroundedGenerationServiceClient, + transports.GroundedGenerationServiceGrpcTransport, + "grpc", + ), + ( + GroundedGenerationServiceAsyncClient, + transports.GroundedGenerationServiceGrpcAsyncIOTransport, + "grpc_asyncio", + ), + ( + GroundedGenerationServiceClient, + transports.GroundedGenerationServiceRestTransport, + "rest", + ), + ], +) +def test_grounded_generation_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", + [ + ( + GroundedGenerationServiceClient, + transports.GroundedGenerationServiceGrpcTransport, + "grpc", + grpc_helpers, + ), + ( + GroundedGenerationServiceAsyncClient, + transports.GroundedGenerationServiceGrpcAsyncIOTransport, + "grpc_asyncio", + grpc_helpers_async, + ), + ( + GroundedGenerationServiceClient, + transports.GroundedGenerationServiceRestTransport, + "rest", + None, + ), + ], +) +def test_grounded_generation_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_grounded_generation_service_client_client_options_from_dict(): + with mock.patch( + "google.cloud.discoveryengine_v1beta.services.grounded_generation_service.transports.GroundedGenerationServiceGrpcTransport.__init__" + ) as grpc_transport: + grpc_transport.return_value = None + client = GroundedGenerationServiceClient( + 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", + [ + ( + GroundedGenerationServiceClient, + transports.GroundedGenerationServiceGrpcTransport, + "grpc", + grpc_helpers, + ), + ( + GroundedGenerationServiceAsyncClient, + transports.GroundedGenerationServiceGrpcAsyncIOTransport, + "grpc_asyncio", + grpc_helpers_async, + ), + ], +) +def test_grounded_generation_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( + "discoveryengine.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="discoveryengine.googleapis.com", + ssl_credentials=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + +@pytest.mark.parametrize( + "request_type", + [ + grounded_generation_service.CheckGroundingRequest, + dict, + ], +) +def test_check_grounding(request_type, transport: str = "grpc"): + client = GroundedGenerationServiceClient( + 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.check_grounding), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grounded_generation_service.CheckGroundingResponse( + support_score=0.1432, + ) + response = client.check_grounding(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = grounded_generation_service.CheckGroundingRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, grounded_generation_service.CheckGroundingResponse) + assert math.isclose(response.support_score, 0.1432, rel_tol=1e-6) + + +def test_check_grounding_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 = GroundedGenerationServiceClient( + 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.check_grounding), "__call__") as call: + client.check_grounding() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == grounded_generation_service.CheckGroundingRequest() + + +def test_check_grounding_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 = GroundedGenerationServiceClient( + 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 = grounded_generation_service.CheckGroundingRequest( + grounding_config="grounding_config_value", + answer_candidate="answer_candidate_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.check_grounding), "__call__") as call: + client.check_grounding(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == grounded_generation_service.CheckGroundingRequest( + grounding_config="grounding_config_value", + answer_candidate="answer_candidate_value", + ) + + +@pytest.mark.asyncio +async def test_check_grounding_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 = GroundedGenerationServiceAsyncClient( + 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.check_grounding), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + grounded_generation_service.CheckGroundingResponse( + support_score=0.1432, + ) + ) + response = await client.check_grounding() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == grounded_generation_service.CheckGroundingRequest() + + +@pytest.mark.asyncio +async def test_check_grounding_async( + transport: str = "grpc_asyncio", + request_type=grounded_generation_service.CheckGroundingRequest, +): + client = GroundedGenerationServiceAsyncClient( + 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.check_grounding), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + grounded_generation_service.CheckGroundingResponse( + support_score=0.1432, + ) + ) + response = await client.check_grounding(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = grounded_generation_service.CheckGroundingRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, grounded_generation_service.CheckGroundingResponse) + assert math.isclose(response.support_score, 0.1432, rel_tol=1e-6) + + +@pytest.mark.asyncio +async def test_check_grounding_async_from_dict(): + await test_check_grounding_async(request_type=dict) + + +def test_check_grounding_field_headers(): + client = GroundedGenerationServiceClient( + 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 = grounded_generation_service.CheckGroundingRequest() + + request.grounding_config = "grounding_config_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.check_grounding), "__call__") as call: + call.return_value = grounded_generation_service.CheckGroundingResponse() + client.check_grounding(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", + "grounding_config=grounding_config_value", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_check_grounding_field_headers_async(): + client = GroundedGenerationServiceAsyncClient( + 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 = grounded_generation_service.CheckGroundingRequest() + + request.grounding_config = "grounding_config_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.check_grounding), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + grounded_generation_service.CheckGroundingResponse() + ) + await client.check_grounding(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", + "grounding_config=grounding_config_value", + ) in kw["metadata"] + + +@pytest.mark.parametrize( + "request_type", + [ + grounded_generation_service.CheckGroundingRequest, + dict, + ], +) +def test_check_grounding_rest(request_type): + client = GroundedGenerationServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = { + "grounding_config": "projects/sample1/locations/sample2/groundingConfigs/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 = grounded_generation_service.CheckGroundingResponse( + support_score=0.1432, + ) + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = grounded_generation_service.CheckGroundingResponse.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.check_grounding(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, grounded_generation_service.CheckGroundingResponse) + assert math.isclose(response.support_score, 0.1432, rel_tol=1e-6) + + +def test_check_grounding_rest_required_fields( + request_type=grounded_generation_service.CheckGroundingRequest, +): + transport_class = transports.GroundedGenerationServiceRestTransport + + request_init = {} + request_init["grounding_config"] = "" + 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() + ).check_grounding._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + jsonified_request["groundingConfig"] = "grounding_config_value" + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).check_grounding._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + assert "groundingConfig" in jsonified_request + assert jsonified_request["groundingConfig"] == "grounding_config_value" + + client = GroundedGenerationServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = grounded_generation_service.CheckGroundingResponse() + # 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 = grounded_generation_service.CheckGroundingResponse.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.check_grounding(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_check_grounding_rest_unset_required_fields(): + transport = transports.GroundedGenerationServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.check_grounding._get_unset_required_fields({}) + assert set(unset_fields) == (set(()) & set(("groundingConfig",))) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_check_grounding_rest_interceptors(null_interceptor): + transport = transports.GroundedGenerationServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.GroundedGenerationServiceRestInterceptor(), + ) + client = GroundedGenerationServiceClient(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.GroundedGenerationServiceRestInterceptor, "post_check_grounding" + ) as post, mock.patch.object( + transports.GroundedGenerationServiceRestInterceptor, "pre_check_grounding" + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = grounded_generation_service.CheckGroundingRequest.pb( + grounded_generation_service.CheckGroundingRequest() + ) + 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 = ( + grounded_generation_service.CheckGroundingResponse.to_json( + grounded_generation_service.CheckGroundingResponse() + ) + ) + + request = grounded_generation_service.CheckGroundingRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = grounded_generation_service.CheckGroundingResponse() + + client.check_grounding( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_check_grounding_rest_bad_request( + transport: str = "rest", + request_type=grounded_generation_service.CheckGroundingRequest, +): + client = GroundedGenerationServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = { + "grounding_config": "projects/sample1/locations/sample2/groundingConfigs/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.check_grounding(request) + + +def test_check_grounding_rest_error(): + client = GroundedGenerationServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + +def test_credentials_transport_error(): + # It is an error to provide credentials and a transport instance. + transport = transports.GroundedGenerationServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + with pytest.raises(ValueError): + client = GroundedGenerationServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # It is an error to provide a credentials file and a transport instance. + transport = transports.GroundedGenerationServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + with pytest.raises(ValueError): + client = GroundedGenerationServiceClient( + client_options={"credentials_file": "credentials.json"}, + transport=transport, + ) + + # It is an error to provide an api_key and a transport instance. + transport = transports.GroundedGenerationServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + options = client_options.ClientOptions() + options.api_key = "api_key" + with pytest.raises(ValueError): + client = GroundedGenerationServiceClient( + 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 = GroundedGenerationServiceClient( + client_options=options, credentials=ga_credentials.AnonymousCredentials() + ) + + # It is an error to provide scopes and a transport instance. + transport = transports.GroundedGenerationServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + with pytest.raises(ValueError): + client = GroundedGenerationServiceClient( + client_options={"scopes": ["1", "2"]}, + transport=transport, + ) + + +def test_transport_instance(): + # A client may be instantiated with a custom transport instance. + transport = transports.GroundedGenerationServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + client = GroundedGenerationServiceClient(transport=transport) + assert client.transport is transport + + +def test_transport_get_channel(): + # A client may be instantiated with a custom transport instance. + transport = transports.GroundedGenerationServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + channel = transport.grpc_channel + assert channel + + transport = transports.GroundedGenerationServiceGrpcAsyncIOTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + channel = transport.grpc_channel + assert channel + + +@pytest.mark.parametrize( + "transport_class", + [ + transports.GroundedGenerationServiceGrpcTransport, + transports.GroundedGenerationServiceGrpcAsyncIOTransport, + transports.GroundedGenerationServiceRestTransport, + ], +) +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 = GroundedGenerationServiceClient.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 = GroundedGenerationServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + assert isinstance( + client.transport, + transports.GroundedGenerationServiceGrpcTransport, + ) + + +def test_grounded_generation_service_base_transport_error(): + # Passing both a credentials object and credentials_file should raise an error + with pytest.raises(core_exceptions.DuplicateCredentialArgs): + transport = transports.GroundedGenerationServiceTransport( + credentials=ga_credentials.AnonymousCredentials(), + credentials_file="credentials.json", + ) + + +def test_grounded_generation_service_base_transport(): + # Instantiate the base transport. + with mock.patch( + "google.cloud.discoveryengine_v1beta.services.grounded_generation_service.transports.GroundedGenerationServiceTransport.__init__" + ) as Transport: + Transport.return_value = None + transport = transports.GroundedGenerationServiceTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Every method on the transport should just blindly + # raise NotImplementedError. + methods = ( + "check_grounding", + "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_grounded_generation_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.discoveryengine_v1beta.services.grounded_generation_service.transports.GroundedGenerationServiceTransport._prep_wrapped_messages" + ) as Transport: + Transport.return_value = None + load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) + transport = transports.GroundedGenerationServiceTransport( + 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_grounded_generation_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.discoveryengine_v1beta.services.grounded_generation_service.transports.GroundedGenerationServiceTransport._prep_wrapped_messages" + ) as Transport: + Transport.return_value = None + adc.return_value = (ga_credentials.AnonymousCredentials(), None) + transport = transports.GroundedGenerationServiceTransport() + adc.assert_called_once() + + +def test_grounded_generation_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) + GroundedGenerationServiceClient() + 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.GroundedGenerationServiceGrpcTransport, + transports.GroundedGenerationServiceGrpcAsyncIOTransport, + ], +) +def test_grounded_generation_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.GroundedGenerationServiceGrpcTransport, + transports.GroundedGenerationServiceGrpcAsyncIOTransport, + transports.GroundedGenerationServiceRestTransport, + ], +) +def test_grounded_generation_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.GroundedGenerationServiceGrpcTransport, grpc_helpers), + (transports.GroundedGenerationServiceGrpcAsyncIOTransport, grpc_helpers_async), + ], +) +def test_grounded_generation_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( + "discoveryengine.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="discoveryengine.googleapis.com", + ssl_credentials=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + +@pytest.mark.parametrize( + "transport_class", + [ + transports.GroundedGenerationServiceGrpcTransport, + transports.GroundedGenerationServiceGrpcAsyncIOTransport, + ], +) +def test_grounded_generation_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_grounded_generation_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.GroundedGenerationServiceRestTransport( + 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_grounded_generation_service_host_no_port(transport_name): + client = GroundedGenerationServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + client_options=client_options.ClientOptions( + api_endpoint="discoveryengine.googleapis.com" + ), + transport=transport_name, + ) + assert client.transport._host == ( + "discoveryengine.googleapis.com:443" + if transport_name in ["grpc", "grpc_asyncio"] + else "https://discoveryengine.googleapis.com" + ) + + +@pytest.mark.parametrize( + "transport_name", + [ + "grpc", + "grpc_asyncio", + "rest", + ], +) +def test_grounded_generation_service_host_with_port(transport_name): + client = GroundedGenerationServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + client_options=client_options.ClientOptions( + api_endpoint="discoveryengine.googleapis.com:8000" + ), + transport=transport_name, + ) + assert client.transport._host == ( + "discoveryengine.googleapis.com:8000" + if transport_name in ["grpc", "grpc_asyncio"] + else "https://discoveryengine.googleapis.com:8000" + ) + + +@pytest.mark.parametrize( + "transport_name", + [ + "rest", + ], +) +def test_grounded_generation_service_client_transport_session_collision(transport_name): + creds1 = ga_credentials.AnonymousCredentials() + creds2 = ga_credentials.AnonymousCredentials() + client1 = GroundedGenerationServiceClient( + credentials=creds1, + transport=transport_name, + ) + client2 = GroundedGenerationServiceClient( + credentials=creds2, + transport=transport_name, + ) + session1 = client1.transport.check_grounding._session + session2 = client2.transport.check_grounding._session + assert session1 != session2 + + +def test_grounded_generation_service_grpc_transport_channel(): + channel = grpc.secure_channel("http://localhost/", grpc.local_channel_credentials()) + + # Check that channel is used if provided. + transport = transports.GroundedGenerationServiceGrpcTransport( + 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_grounded_generation_service_grpc_asyncio_transport_channel(): + channel = aio.secure_channel("http://localhost/", grpc.local_channel_credentials()) + + # Check that channel is used if provided. + transport = transports.GroundedGenerationServiceGrpcAsyncIOTransport( + 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.GroundedGenerationServiceGrpcTransport, + transports.GroundedGenerationServiceGrpcAsyncIOTransport, + ], +) +def test_grounded_generation_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.GroundedGenerationServiceGrpcTransport, + transports.GroundedGenerationServiceGrpcAsyncIOTransport, + ], +) +def test_grounded_generation_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_grounding_config_path(): + project = "squid" + location = "clam" + grounding_config = "whelk" + expected = "projects/{project}/locations/{location}/groundingConfigs/{grounding_config}".format( + project=project, + location=location, + grounding_config=grounding_config, + ) + actual = GroundedGenerationServiceClient.grounding_config_path( + project, location, grounding_config + ) + assert expected == actual + + +def test_parse_grounding_config_path(): + expected = { + "project": "octopus", + "location": "oyster", + "grounding_config": "nudibranch", + } + path = GroundedGenerationServiceClient.grounding_config_path(**expected) + + # Check that the path construction is reversible. + actual = GroundedGenerationServiceClient.parse_grounding_config_path(path) + assert expected == actual + + +def test_common_billing_account_path(): + billing_account = "cuttlefish" + expected = "billingAccounts/{billing_account}".format( + billing_account=billing_account, + ) + actual = GroundedGenerationServiceClient.common_billing_account_path( + billing_account + ) + assert expected == actual + + +def test_parse_common_billing_account_path(): + expected = { + "billing_account": "mussel", + } + path = GroundedGenerationServiceClient.common_billing_account_path(**expected) + + # Check that the path construction is reversible. + actual = GroundedGenerationServiceClient.parse_common_billing_account_path(path) + assert expected == actual + + +def test_common_folder_path(): + folder = "winkle" + expected = "folders/{folder}".format( + folder=folder, + ) + actual = GroundedGenerationServiceClient.common_folder_path(folder) + assert expected == actual + + +def test_parse_common_folder_path(): + expected = { + "folder": "nautilus", + } + path = GroundedGenerationServiceClient.common_folder_path(**expected) + + # Check that the path construction is reversible. + actual = GroundedGenerationServiceClient.parse_common_folder_path(path) + assert expected == actual + + +def test_common_organization_path(): + organization = "scallop" + expected = "organizations/{organization}".format( + organization=organization, + ) + actual = GroundedGenerationServiceClient.common_organization_path(organization) + assert expected == actual + + +def test_parse_common_organization_path(): + expected = { + "organization": "abalone", + } + path = GroundedGenerationServiceClient.common_organization_path(**expected) + + # Check that the path construction is reversible. + actual = GroundedGenerationServiceClient.parse_common_organization_path(path) + assert expected == actual + + +def test_common_project_path(): + project = "squid" + expected = "projects/{project}".format( + project=project, + ) + actual = GroundedGenerationServiceClient.common_project_path(project) + assert expected == actual + + +def test_parse_common_project_path(): + expected = { + "project": "clam", + } + path = GroundedGenerationServiceClient.common_project_path(**expected) + + # Check that the path construction is reversible. + actual = GroundedGenerationServiceClient.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 = GroundedGenerationServiceClient.common_location_path(project, location) + assert expected == actual + + +def test_parse_common_location_path(): + expected = { + "project": "oyster", + "location": "nudibranch", + } + path = GroundedGenerationServiceClient.common_location_path(**expected) + + # Check that the path construction is reversible. + actual = GroundedGenerationServiceClient.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.GroundedGenerationServiceTransport, "_prep_wrapped_messages" + ) as prep: + client = GroundedGenerationServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + client_info=client_info, + ) + prep.assert_called_once_with(client_info) + + with mock.patch.object( + transports.GroundedGenerationServiceTransport, "_prep_wrapped_messages" + ) as prep: + transport_class = GroundedGenerationServiceClient.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 = GroundedGenerationServiceAsyncClient( + 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 = GroundedGenerationServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + request = request_type() + request = json_format.ParseDict( + { + "name": "projects/sample1/locations/sample2/collections/sample3/dataConnector/operations/sample4" + }, + 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 = GroundedGenerationServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request_init = { + "name": "projects/sample1/locations/sample2/collections/sample3/dataConnector/operations/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() + + # 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 = GroundedGenerationServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + request = request_type() + request = json_format.ParseDict( + { + "name": "projects/sample1/locations/sample2/collections/sample3/dataConnector" + }, + 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 = GroundedGenerationServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request_init = { + "name": "projects/sample1/locations/sample2/collections/sample3/dataConnector" + } + 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 = GroundedGenerationServiceClient( + 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 = GroundedGenerationServiceAsyncClient( + 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 = GroundedGenerationServiceClient( + 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 = GroundedGenerationServiceAsyncClient( + 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 = GroundedGenerationServiceClient( + 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 = GroundedGenerationServiceAsyncClient( + 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 = GroundedGenerationServiceClient( + 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 = GroundedGenerationServiceAsyncClient( + 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 = GroundedGenerationServiceClient( + 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 = GroundedGenerationServiceAsyncClient( + 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 = GroundedGenerationServiceClient( + 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 = GroundedGenerationServiceAsyncClient( + 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 = GroundedGenerationServiceClient( + 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 = GroundedGenerationServiceClient( + 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", + [ + ( + GroundedGenerationServiceClient, + transports.GroundedGenerationServiceGrpcTransport, + ), + ( + GroundedGenerationServiceAsyncClient, + transports.GroundedGenerationServiceGrpcAsyncIOTransport, + ), + ], +) +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-discoveryengine/tests/unit/gapic/discoveryengine_v1beta/test_rank_service.py b/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1beta/test_rank_service.py new file mode 100644 index 000000000000..da91de6f0829 --- /dev/null +++ b/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1beta/test_rank_service.py @@ -0,0 +1,2662 @@ +# -*- 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 +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 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.discoveryengine_v1beta.services.rank_service import ( + RankServiceAsyncClient, + RankServiceClient, + transports, +) +from google.cloud.discoveryengine_v1beta.types import rank_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 RankServiceClient._get_default_mtls_endpoint(None) is None + assert ( + RankServiceClient._get_default_mtls_endpoint(api_endpoint) == api_mtls_endpoint + ) + assert ( + RankServiceClient._get_default_mtls_endpoint(api_mtls_endpoint) + == api_mtls_endpoint + ) + assert ( + RankServiceClient._get_default_mtls_endpoint(sandbox_endpoint) + == sandbox_mtls_endpoint + ) + assert ( + RankServiceClient._get_default_mtls_endpoint(sandbox_mtls_endpoint) + == sandbox_mtls_endpoint + ) + assert RankServiceClient._get_default_mtls_endpoint(non_googleapi) == non_googleapi + + +def test__read_environment_variables(): + assert RankServiceClient._read_environment_variables() == (False, "auto", None) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "true"}): + assert RankServiceClient._read_environment_variables() == (True, "auto", None) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "false"}): + assert RankServiceClient._read_environment_variables() == (False, "auto", None) + + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"} + ): + with pytest.raises(ValueError) as excinfo: + RankServiceClient._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 RankServiceClient._read_environment_variables() == (False, "never", None) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): + assert RankServiceClient._read_environment_variables() == ( + False, + "always", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "auto"}): + assert RankServiceClient._read_environment_variables() == (False, "auto", None) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "Unsupported"}): + with pytest.raises(MutualTLSChannelError) as excinfo: + RankServiceClient._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 RankServiceClient._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 RankServiceClient._get_client_cert_source(None, False) is None + assert ( + RankServiceClient._get_client_cert_source(mock_provided_cert_source, False) + is None + ) + assert ( + RankServiceClient._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 ( + RankServiceClient._get_client_cert_source(None, True) + is mock_default_cert_source + ) + assert ( + RankServiceClient._get_client_cert_source( + mock_provided_cert_source, "true" + ) + is mock_provided_cert_source + ) + + +@mock.patch.object( + RankServiceClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(RankServiceClient), +) +@mock.patch.object( + RankServiceAsyncClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(RankServiceAsyncClient), +) +def test__get_api_endpoint(): + api_override = "foo.com" + mock_client_cert_source = mock.Mock() + default_universe = RankServiceClient._DEFAULT_UNIVERSE + default_endpoint = RankServiceClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=default_universe + ) + mock_universe = "bar.com" + mock_endpoint = RankServiceClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=mock_universe + ) + + assert ( + RankServiceClient._get_api_endpoint( + api_override, mock_client_cert_source, default_universe, "always" + ) + == api_override + ) + assert ( + RankServiceClient._get_api_endpoint( + None, mock_client_cert_source, default_universe, "auto" + ) + == RankServiceClient.DEFAULT_MTLS_ENDPOINT + ) + assert ( + RankServiceClient._get_api_endpoint(None, None, default_universe, "auto") + == default_endpoint + ) + assert ( + RankServiceClient._get_api_endpoint(None, None, default_universe, "always") + == RankServiceClient.DEFAULT_MTLS_ENDPOINT + ) + assert ( + RankServiceClient._get_api_endpoint( + None, mock_client_cert_source, default_universe, "always" + ) + == RankServiceClient.DEFAULT_MTLS_ENDPOINT + ) + assert ( + RankServiceClient._get_api_endpoint(None, None, mock_universe, "never") + == mock_endpoint + ) + assert ( + RankServiceClient._get_api_endpoint(None, None, default_universe, "never") + == default_endpoint + ) + + with pytest.raises(MutualTLSChannelError) as excinfo: + RankServiceClient._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 ( + RankServiceClient._get_universe_domain( + client_universe_domain, universe_domain_env + ) + == client_universe_domain + ) + assert ( + RankServiceClient._get_universe_domain(None, universe_domain_env) + == universe_domain_env + ) + assert ( + RankServiceClient._get_universe_domain(None, None) + == RankServiceClient._DEFAULT_UNIVERSE + ) + + with pytest.raises(ValueError) as excinfo: + RankServiceClient._get_universe_domain("", None) + assert str(excinfo.value) == "Universe Domain cannot be an empty string." + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name", + [ + (RankServiceClient, transports.RankServiceGrpcTransport, "grpc"), + (RankServiceClient, transports.RankServiceRestTransport, "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", + [ + (RankServiceClient, "grpc"), + (RankServiceAsyncClient, "grpc_asyncio"), + (RankServiceClient, "rest"), + ], +) +def test_rank_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 == ( + "discoveryengine.googleapis.com:443" + if transport_name in ["grpc", "grpc_asyncio"] + else "https://discoveryengine.googleapis.com" + ) + + +@pytest.mark.parametrize( + "transport_class,transport_name", + [ + (transports.RankServiceGrpcTransport, "grpc"), + (transports.RankServiceGrpcAsyncIOTransport, "grpc_asyncio"), + (transports.RankServiceRestTransport, "rest"), + ], +) +def test_rank_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", + [ + (RankServiceClient, "grpc"), + (RankServiceAsyncClient, "grpc_asyncio"), + (RankServiceClient, "rest"), + ], +) +def test_rank_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 == ( + "discoveryengine.googleapis.com:443" + if transport_name in ["grpc", "grpc_asyncio"] + else "https://discoveryengine.googleapis.com" + ) + + +def test_rank_service_client_get_transport_class(): + transport = RankServiceClient.get_transport_class() + available_transports = [ + transports.RankServiceGrpcTransport, + transports.RankServiceRestTransport, + ] + assert transport in available_transports + + transport = RankServiceClient.get_transport_class("grpc") + assert transport == transports.RankServiceGrpcTransport + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name", + [ + (RankServiceClient, transports.RankServiceGrpcTransport, "grpc"), + ( + RankServiceAsyncClient, + transports.RankServiceGrpcAsyncIOTransport, + "grpc_asyncio", + ), + (RankServiceClient, transports.RankServiceRestTransport, "rest"), + ], +) +@mock.patch.object( + RankServiceClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(RankServiceClient), +) +@mock.patch.object( + RankServiceAsyncClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(RankServiceAsyncClient), +) +def test_rank_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(RankServiceClient, "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(RankServiceClient, "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", + [ + (RankServiceClient, transports.RankServiceGrpcTransport, "grpc", "true"), + ( + RankServiceAsyncClient, + transports.RankServiceGrpcAsyncIOTransport, + "grpc_asyncio", + "true", + ), + (RankServiceClient, transports.RankServiceGrpcTransport, "grpc", "false"), + ( + RankServiceAsyncClient, + transports.RankServiceGrpcAsyncIOTransport, + "grpc_asyncio", + "false", + ), + (RankServiceClient, transports.RankServiceRestTransport, "rest", "true"), + (RankServiceClient, transports.RankServiceRestTransport, "rest", "false"), + ], +) +@mock.patch.object( + RankServiceClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(RankServiceClient), +) +@mock.patch.object( + RankServiceAsyncClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(RankServiceAsyncClient), +) +@mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "auto"}) +def test_rank_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", [RankServiceClient, RankServiceAsyncClient]) +@mock.patch.object( + RankServiceClient, "DEFAULT_ENDPOINT", modify_default_endpoint(RankServiceClient) +) +@mock.patch.object( + RankServiceAsyncClient, + "DEFAULT_ENDPOINT", + modify_default_endpoint(RankServiceAsyncClient), +) +def test_rank_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", [RankServiceClient, RankServiceAsyncClient]) +@mock.patch.object( + RankServiceClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(RankServiceClient), +) +@mock.patch.object( + RankServiceAsyncClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(RankServiceAsyncClient), +) +def test_rank_service_client_client_api_endpoint(client_class): + mock_client_cert_source = client_cert_source_callback + api_override = "foo.com" + default_universe = RankServiceClient._DEFAULT_UNIVERSE + default_endpoint = RankServiceClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=default_universe + ) + mock_universe = "bar.com" + mock_endpoint = RankServiceClient._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", + [ + (RankServiceClient, transports.RankServiceGrpcTransport, "grpc"), + ( + RankServiceAsyncClient, + transports.RankServiceGrpcAsyncIOTransport, + "grpc_asyncio", + ), + (RankServiceClient, transports.RankServiceRestTransport, "rest"), + ], +) +def test_rank_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", + [ + (RankServiceClient, transports.RankServiceGrpcTransport, "grpc", grpc_helpers), + ( + RankServiceAsyncClient, + transports.RankServiceGrpcAsyncIOTransport, + "grpc_asyncio", + grpc_helpers_async, + ), + (RankServiceClient, transports.RankServiceRestTransport, "rest", None), + ], +) +def test_rank_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_rank_service_client_client_options_from_dict(): + with mock.patch( + "google.cloud.discoveryengine_v1beta.services.rank_service.transports.RankServiceGrpcTransport.__init__" + ) as grpc_transport: + grpc_transport.return_value = None + client = RankServiceClient(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", + [ + (RankServiceClient, transports.RankServiceGrpcTransport, "grpc", grpc_helpers), + ( + RankServiceAsyncClient, + transports.RankServiceGrpcAsyncIOTransport, + "grpc_asyncio", + grpc_helpers_async, + ), + ], +) +def test_rank_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( + "discoveryengine.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="discoveryengine.googleapis.com", + ssl_credentials=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + +@pytest.mark.parametrize( + "request_type", + [ + rank_service.RankRequest, + dict, + ], +) +def test_rank(request_type, transport: str = "grpc"): + client = RankServiceClient( + 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.rank), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = rank_service.RankResponse() + response = client.rank(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = rank_service.RankRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, rank_service.RankResponse) + + +def test_rank_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 = RankServiceClient( + 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.rank), "__call__") as call: + client.rank() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == rank_service.RankRequest() + + +def test_rank_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 = RankServiceClient( + 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 = rank_service.RankRequest( + ranking_config="ranking_config_value", + model="model_value", + query="query_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.rank), "__call__") as call: + client.rank(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == rank_service.RankRequest( + ranking_config="ranking_config_value", + model="model_value", + query="query_value", + ) + + +@pytest.mark.asyncio +async def test_rank_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 = RankServiceAsyncClient( + 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.rank), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + rank_service.RankResponse() + ) + response = await client.rank() + call.assert_called() + _, args, _ = call.mock_calls[0] + assert args[0] == rank_service.RankRequest() + + +@pytest.mark.asyncio +async def test_rank_async( + transport: str = "grpc_asyncio", request_type=rank_service.RankRequest +): + client = RankServiceAsyncClient( + 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.rank), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + rank_service.RankResponse() + ) + response = await client.rank(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = rank_service.RankRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, rank_service.RankResponse) + + +@pytest.mark.asyncio +async def test_rank_async_from_dict(): + await test_rank_async(request_type=dict) + + +def test_rank_field_headers(): + client = RankServiceClient( + 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 = rank_service.RankRequest() + + request.ranking_config = "ranking_config_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.rank), "__call__") as call: + call.return_value = rank_service.RankResponse() + client.rank(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", + "ranking_config=ranking_config_value", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_rank_field_headers_async(): + client = RankServiceAsyncClient( + 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 = rank_service.RankRequest() + + request.ranking_config = "ranking_config_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.rank), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + rank_service.RankResponse() + ) + await client.rank(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", + "ranking_config=ranking_config_value", + ) in kw["metadata"] + + +@pytest.mark.parametrize( + "request_type", + [ + rank_service.RankRequest, + dict, + ], +) +def test_rank_rest(request_type): + client = RankServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # send a request that will satisfy transcoding + request_init = { + "ranking_config": "projects/sample1/locations/sample2/rankingConfigs/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 = rank_service.RankResponse() + + # Wrap the value into a proper Response obj + response_value = Response() + response_value.status_code = 200 + # Convert return value to protobuf type + return_value = rank_service.RankResponse.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.rank(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, rank_service.RankResponse) + + +def test_rank_rest_required_fields(request_type=rank_service.RankRequest): + transport_class = transports.RankServiceRestTransport + + request_init = {} + request_init["ranking_config"] = "" + 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() + ).rank._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + jsonified_request["rankingConfig"] = "ranking_config_value" + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).rank._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + assert "rankingConfig" in jsonified_request + assert jsonified_request["rankingConfig"] == "ranking_config_value" + + client = RankServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = rank_service.RankResponse() + # 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 = rank_service.RankResponse.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.rank(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert expected_params == actual_params + + +def test_rank_rest_unset_required_fields(): + transport = transports.RankServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.rank._get_unset_required_fields({}) + assert set(unset_fields) == ( + set(()) + & set( + ( + "rankingConfig", + "records", + ) + ) + ) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_rank_rest_interceptors(null_interceptor): + transport = transports.RankServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.RankServiceRestInterceptor(), + ) + client = RankServiceClient(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.RankServiceRestInterceptor, "post_rank" + ) as post, mock.patch.object( + transports.RankServiceRestInterceptor, "pre_rank" + ) as pre: + pre.assert_not_called() + post.assert_not_called() + pb_message = rank_service.RankRequest.pb(rank_service.RankRequest()) + 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 = rank_service.RankResponse.to_json( + rank_service.RankResponse() + ) + + request = rank_service.RankRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = rank_service.RankResponse() + + client.rank( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + + +def test_rank_rest_bad_request( + transport: str = "rest", request_type=rank_service.RankRequest +): + client = RankServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # send a request that will satisfy transcoding + request_init = { + "ranking_config": "projects/sample1/locations/sample2/rankingConfigs/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.rank(request) + + +def test_rank_rest_error(): + client = RankServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + +def test_credentials_transport_error(): + # It is an error to provide credentials and a transport instance. + transport = transports.RankServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + with pytest.raises(ValueError): + client = RankServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # It is an error to provide a credentials file and a transport instance. + transport = transports.RankServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + with pytest.raises(ValueError): + client = RankServiceClient( + client_options={"credentials_file": "credentials.json"}, + transport=transport, + ) + + # It is an error to provide an api_key and a transport instance. + transport = transports.RankServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + options = client_options.ClientOptions() + options.api_key = "api_key" + with pytest.raises(ValueError): + client = RankServiceClient( + 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 = RankServiceClient( + client_options=options, credentials=ga_credentials.AnonymousCredentials() + ) + + # It is an error to provide scopes and a transport instance. + transport = transports.RankServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + with pytest.raises(ValueError): + client = RankServiceClient( + client_options={"scopes": ["1", "2"]}, + transport=transport, + ) + + +def test_transport_instance(): + # A client may be instantiated with a custom transport instance. + transport = transports.RankServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + client = RankServiceClient(transport=transport) + assert client.transport is transport + + +def test_transport_get_channel(): + # A client may be instantiated with a custom transport instance. + transport = transports.RankServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + channel = transport.grpc_channel + assert channel + + transport = transports.RankServiceGrpcAsyncIOTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + channel = transport.grpc_channel + assert channel + + +@pytest.mark.parametrize( + "transport_class", + [ + transports.RankServiceGrpcTransport, + transports.RankServiceGrpcAsyncIOTransport, + transports.RankServiceRestTransport, + ], +) +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 = RankServiceClient.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 = RankServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + assert isinstance( + client.transport, + transports.RankServiceGrpcTransport, + ) + + +def test_rank_service_base_transport_error(): + # Passing both a credentials object and credentials_file should raise an error + with pytest.raises(core_exceptions.DuplicateCredentialArgs): + transport = transports.RankServiceTransport( + credentials=ga_credentials.AnonymousCredentials(), + credentials_file="credentials.json", + ) + + +def test_rank_service_base_transport(): + # Instantiate the base transport. + with mock.patch( + "google.cloud.discoveryengine_v1beta.services.rank_service.transports.RankServiceTransport.__init__" + ) as Transport: + Transport.return_value = None + transport = transports.RankServiceTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Every method on the transport should just blindly + # raise NotImplementedError. + methods = ( + "rank", + "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_rank_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.discoveryengine_v1beta.services.rank_service.transports.RankServiceTransport._prep_wrapped_messages" + ) as Transport: + Transport.return_value = None + load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) + transport = transports.RankServiceTransport( + 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_rank_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.discoveryengine_v1beta.services.rank_service.transports.RankServiceTransport._prep_wrapped_messages" + ) as Transport: + Transport.return_value = None + adc.return_value = (ga_credentials.AnonymousCredentials(), None) + transport = transports.RankServiceTransport() + adc.assert_called_once() + + +def test_rank_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) + RankServiceClient() + 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.RankServiceGrpcTransport, + transports.RankServiceGrpcAsyncIOTransport, + ], +) +def test_rank_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.RankServiceGrpcTransport, + transports.RankServiceGrpcAsyncIOTransport, + transports.RankServiceRestTransport, + ], +) +def test_rank_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.RankServiceGrpcTransport, grpc_helpers), + (transports.RankServiceGrpcAsyncIOTransport, grpc_helpers_async), + ], +) +def test_rank_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( + "discoveryengine.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="discoveryengine.googleapis.com", + ssl_credentials=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + +@pytest.mark.parametrize( + "transport_class", + [transports.RankServiceGrpcTransport, transports.RankServiceGrpcAsyncIOTransport], +) +def test_rank_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_rank_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.RankServiceRestTransport( + 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_rank_service_host_no_port(transport_name): + client = RankServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + client_options=client_options.ClientOptions( + api_endpoint="discoveryengine.googleapis.com" + ), + transport=transport_name, + ) + assert client.transport._host == ( + "discoveryengine.googleapis.com:443" + if transport_name in ["grpc", "grpc_asyncio"] + else "https://discoveryengine.googleapis.com" + ) + + +@pytest.mark.parametrize( + "transport_name", + [ + "grpc", + "grpc_asyncio", + "rest", + ], +) +def test_rank_service_host_with_port(transport_name): + client = RankServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + client_options=client_options.ClientOptions( + api_endpoint="discoveryengine.googleapis.com:8000" + ), + transport=transport_name, + ) + assert client.transport._host == ( + "discoveryengine.googleapis.com:8000" + if transport_name in ["grpc", "grpc_asyncio"] + else "https://discoveryengine.googleapis.com:8000" + ) + + +@pytest.mark.parametrize( + "transport_name", + [ + "rest", + ], +) +def test_rank_service_client_transport_session_collision(transport_name): + creds1 = ga_credentials.AnonymousCredentials() + creds2 = ga_credentials.AnonymousCredentials() + client1 = RankServiceClient( + credentials=creds1, + transport=transport_name, + ) + client2 = RankServiceClient( + credentials=creds2, + transport=transport_name, + ) + session1 = client1.transport.rank._session + session2 = client2.transport.rank._session + assert session1 != session2 + + +def test_rank_service_grpc_transport_channel(): + channel = grpc.secure_channel("http://localhost/", grpc.local_channel_credentials()) + + # Check that channel is used if provided. + transport = transports.RankServiceGrpcTransport( + 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_rank_service_grpc_asyncio_transport_channel(): + channel = aio.secure_channel("http://localhost/", grpc.local_channel_credentials()) + + # Check that channel is used if provided. + transport = transports.RankServiceGrpcAsyncIOTransport( + 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.RankServiceGrpcTransport, transports.RankServiceGrpcAsyncIOTransport], +) +def test_rank_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.RankServiceGrpcTransport, transports.RankServiceGrpcAsyncIOTransport], +) +def test_rank_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_ranking_config_path(): + project = "squid" + location = "clam" + ranking_config = "whelk" + expected = "projects/{project}/locations/{location}/rankingConfigs/{ranking_config}".format( + project=project, + location=location, + ranking_config=ranking_config, + ) + actual = RankServiceClient.ranking_config_path(project, location, ranking_config) + assert expected == actual + + +def test_parse_ranking_config_path(): + expected = { + "project": "octopus", + "location": "oyster", + "ranking_config": "nudibranch", + } + path = RankServiceClient.ranking_config_path(**expected) + + # Check that the path construction is reversible. + actual = RankServiceClient.parse_ranking_config_path(path) + assert expected == actual + + +def test_common_billing_account_path(): + billing_account = "cuttlefish" + expected = "billingAccounts/{billing_account}".format( + billing_account=billing_account, + ) + actual = RankServiceClient.common_billing_account_path(billing_account) + assert expected == actual + + +def test_parse_common_billing_account_path(): + expected = { + "billing_account": "mussel", + } + path = RankServiceClient.common_billing_account_path(**expected) + + # Check that the path construction is reversible. + actual = RankServiceClient.parse_common_billing_account_path(path) + assert expected == actual + + +def test_common_folder_path(): + folder = "winkle" + expected = "folders/{folder}".format( + folder=folder, + ) + actual = RankServiceClient.common_folder_path(folder) + assert expected == actual + + +def test_parse_common_folder_path(): + expected = { + "folder": "nautilus", + } + path = RankServiceClient.common_folder_path(**expected) + + # Check that the path construction is reversible. + actual = RankServiceClient.parse_common_folder_path(path) + assert expected == actual + + +def test_common_organization_path(): + organization = "scallop" + expected = "organizations/{organization}".format( + organization=organization, + ) + actual = RankServiceClient.common_organization_path(organization) + assert expected == actual + + +def test_parse_common_organization_path(): + expected = { + "organization": "abalone", + } + path = RankServiceClient.common_organization_path(**expected) + + # Check that the path construction is reversible. + actual = RankServiceClient.parse_common_organization_path(path) + assert expected == actual + + +def test_common_project_path(): + project = "squid" + expected = "projects/{project}".format( + project=project, + ) + actual = RankServiceClient.common_project_path(project) + assert expected == actual + + +def test_parse_common_project_path(): + expected = { + "project": "clam", + } + path = RankServiceClient.common_project_path(**expected) + + # Check that the path construction is reversible. + actual = RankServiceClient.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 = RankServiceClient.common_location_path(project, location) + assert expected == actual + + +def test_parse_common_location_path(): + expected = { + "project": "oyster", + "location": "nudibranch", + } + path = RankServiceClient.common_location_path(**expected) + + # Check that the path construction is reversible. + actual = RankServiceClient.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.RankServiceTransport, "_prep_wrapped_messages" + ) as prep: + client = RankServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + client_info=client_info, + ) + prep.assert_called_once_with(client_info) + + with mock.patch.object( + transports.RankServiceTransport, "_prep_wrapped_messages" + ) as prep: + transport_class = RankServiceClient.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 = RankServiceAsyncClient( + 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 = RankServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + request = request_type() + request = json_format.ParseDict( + { + "name": "projects/sample1/locations/sample2/collections/sample3/dataConnector/operations/sample4" + }, + 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 = RankServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request_init = { + "name": "projects/sample1/locations/sample2/collections/sample3/dataConnector/operations/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() + + # 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 = RankServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + request = request_type() + request = json_format.ParseDict( + { + "name": "projects/sample1/locations/sample2/collections/sample3/dataConnector" + }, + 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 = RankServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request_init = { + "name": "projects/sample1/locations/sample2/collections/sample3/dataConnector" + } + 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 = RankServiceClient( + 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 = RankServiceAsyncClient( + 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 = RankServiceClient( + 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 = RankServiceAsyncClient( + 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 = RankServiceClient( + 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 = RankServiceAsyncClient( + 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 = RankServiceClient( + 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 = RankServiceAsyncClient( + 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 = RankServiceClient( + 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 = RankServiceAsyncClient( + 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 = RankServiceClient( + 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 = RankServiceAsyncClient( + 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 = RankServiceClient( + 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 = RankServiceClient( + 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", + [ + (RankServiceClient, transports.RankServiceGrpcTransport), + (RankServiceAsyncClient, transports.RankServiceGrpcAsyncIOTransport), + ], +) +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-discoveryengine/tests/unit/gapic/discoveryengine_v1beta/test_serving_config_service.py b/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1beta/test_serving_config_service.py index 7d246b6b2dff..4288bc2d17a7 100644 --- a/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1beta/test_serving_config_service.py +++ b/packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1beta/test_serving_config_service.py @@ -2497,6 +2497,7 @@ def test_update_serving_config_rest(request_type): "model_prompt_spec": {"preamble": "preamble_value"}, "language_code": "language_code_value", "model_spec": {"version": "version_value"}, + "use_semantic_chunks": True, }, "extractive_content_spec": { "max_extractive_answer_count": 2907,