From b460c092d8feb9cd2bdc25005ba36905184f7e29 Mon Sep 17 00:00:00 2001 From: JoeWang1127 Date: Tue, 23 Jun 2026 21:20:24 +0000 Subject: [PATCH] feat: update googleapis and regenerate --- librarian.yaml | 4 +- .../google/ads/datamanager/__init__.py | 38 + .../google/ads/datamanager_v1/__init__.py | 40 +- .../ads/datamanager_v1/gapic_metadata.json | 15 + .../ingestion_service/async_client.py | 102 + .../services/ingestion_service/client.py | 100 + .../ingestion_service/transports/base.py | 17 + .../ingestion_service/transports/grpc.py | 32 + .../transports/grpc_asyncio.py | 37 + .../ingestion_service/transports/rest.py | 224 + .../ingestion_service/transports/rest_base.py | 57 + .../partner_link_service/async_client.py | 2 + .../services/partner_link_service/client.py | 2 + .../ads/datamanager_v1/types/__init__.py | 38 + .../ads/datamanager_v1/types/ad_event.py | 613 + .../ads/datamanager_v1/types/destination.py | 2 +- .../datamanager_v1/types/encryption_info.py | 33 + .../google/ads/datamanager_v1/types/error.py | 4 +- .../datamanager_v1/types/ingestion_service.py | 39 +- .../types/partner_link_service.py | 97 + .../datamanager_v1/types/viewability_info.py | 145 + ...ngestion_service_ingest_ad_events_async.py | 70 + ...ingestion_service_ingest_ad_events_sync.py | 70 + ...n_service_ingest_audience_members_async.py | 1 + ...on_service_ingest_audience_members_sync.py | 1 + ...d_ingestion_service_ingest_events_async.py | 1 + ...ed_ingestion_service_ingest_events_sync.py | 1 + ...n_service_remove_audience_members_async.py | 1 + ...on_service_remove_audience_members_sync.py | 1 + ..._link_service_create_partner_link_async.py | 2 + ...r_link_service_create_partner_link_sync.py | 2 + ...et_metadata_google.ads.datamanager.v1.json | 265 +- .../datamanager_v1/test_ingestion_service.py | 494 + .../test_partner_link_service.py | 23 + .../google/analytics/admin/__init__.py | 2 + .../analytics/admin_v1alpha/__init__.py | 2 + .../admin_v1alpha/gapic_metadata.json | 15 + .../analytics_admin_service/async_client.py | 115 + .../analytics_admin_service/client.py | 114 + .../transports/base.py | 17 + .../transports/grpc.py | 33 + .../transports/grpc_asyncio.py | 38 + .../transports/rest.py | 235 + .../transports/rest_base.py | 59 + .../analytics/admin_v1alpha/types/__init__.py | 2 + .../admin_v1alpha/types/analytics_admin.py | 29 + .../admin_v1alpha/types/resources.py | 7 + .../admin_v1beta/types/analytics_admin.py | 116 +- .../analytics/admin_v1beta/types/resources.py | 80 +- .../test_analytics_admin_service.py | 870 + .../google/apps/chat_v1/types/message.py | 13 +- .../cloudbuild_v1/types/cloudbuild.py | 3 + .../cloud/ces_v1beta/types/agent_tool.py | 9 - .../gapic/ces_v1beta/test_agent_service.py | 3 - .../rule_execution_error_service.rst | 10 + .../docs/chronicle_v1/services_.rst | 1 + .../google/cloud/chronicle/__init__.py | 26 + .../google/cloud/chronicle_v1/__init__.py | 24 + .../cloud/chronicle_v1/gapic_metadata.json | 64 + .../reference_list_service/async_client.py | 93 + .../services/reference_list_service/client.py | 111 + .../reference_list_service/transports/base.py | 32 +- .../reference_list_service/transports/grpc.py | 30 + .../transports/grpc_asyncio.py | 44 + .../reference_list_service/transports/rest.py | 226 + .../transports/rest_base.py | 57 + .../rule_execution_error_service/__init__.py | 22 + .../async_client.py | 708 + .../rule_execution_error_service/client.py | 1188 ++ .../rule_execution_error_service/pagers.py | 201 + .../transports/README.rst | 10 + .../transports/__init__.py | 39 + .../transports/base.py | 251 + .../transports/grpc.py | 439 + .../transports/grpc_asyncio.py | 491 + .../transports/rest.py | 1029 ++ .../transports/rest_base.py | 245 + .../services/rule_service/async_client.py | 125 + .../services/rule_service/client.py | 142 + .../services/rule_service/transports/base.py | 29 +- .../services/rule_service/transports/grpc.py | 26 + .../rule_service/transports/grpc_asyncio.py | 40 + .../services/rule_service/transports/rest.py | 217 + .../rule_service/transports/rest_base.py | 57 + .../cloud/chronicle_v1/types/__init__.py | 18 + .../chronicle_v1/types/reference_list.py | 78 + .../google/cloud/chronicle_v1/types/rule.py | 51 + .../types/rule_execution_error.py | 192 + ...ist_service_verify_reference_list_async.py | 58 + ...list_service_verify_reference_list_sync.py | 58 + ...ervice_list_rule_execution_errors_async.py | 54 + ...service_list_rule_execution_errors_sync.py | 54 + ...ted_rule_service_verify_rule_text_async.py | 54 + ...ated_rule_service_verify_rule_text_sync.py | 54 + ...et_metadata_google.cloud.chronicle.v1.json | 483 + .../test_reference_list_service.py | 753 +- .../test_rule_execution_error_service.py | 4317 +++++ .../gapic/chronicle_v1/test_rule_service.py | 914 +- .../google/cloud/dataform/__init__.py | 16 + .../google/cloud/dataform_v1beta1/__init__.py | 16 + .../dataform_v1beta1/gapic_metadata.json | 45 + .../services/dataform/async_client.py | 463 +- .../services/dataform/client.py | 476 +- .../services/dataform/transports/base.py | 42 + .../services/dataform/transports/grpc.py | 86 + .../dataform/transports/grpc_asyncio.py | 106 + .../services/dataform/transports/rest.py | 883 +- .../services/dataform/transports/rest_base.py | 171 + .../cloud/dataform_v1beta1/types/__init__.py | 16 + .../cloud/dataform_v1beta1/types/dataform.py | 392 +- ...ated_dataform_delete_folder_tree_async.py} | 22 +- ...rated_dataform_delete_folder_tree_sync.py} | 22 +- ...rm_delete_repository_long_running_async.py | 57 + ...orm_delete_repository_long_running_sync.py | 57 + ..._dataform_delete_team_folder_tree_async.py | 57 + ...d_dataform_delete_team_folder_tree_sync.py | 57 + ...etadata_google.cloud.dataform.v1beta1.json | 507 + .../gapic/dataform_v1beta1/test_dataform.py | 2395 ++- .../cloud/dataproc_v1/types/clusters.py | 52 +- .../dataproc_v1/test_cluster_controller.py | 12 +- .../test_workflow_template_service.py | 12 +- .../dialogflowcx_v3/types/audio_config.py | 2 +- .../cloud/dialogflowcx_v3/types/session.py | 8 + .../types/audio_config.py | 2 +- .../dialogflowcx_v3beta1/types/session.py | 6 + .../google/cloud/dialogflow/__init__.py | 2 + .../google/cloud/dialogflow_v2/__init__.py | 2 + .../services/participants/async_client.py | 10 +- .../services/participants/client.py | 10 +- .../cloud/dialogflow_v2/types/__init__.py | 2 + .../cloud/dialogflow_v2/types/audio_config.py | 2 +- .../cloud/dialogflow_v2/types/ces_app.py | 26 + .../cloud/dialogflow_v2/types/conversation.py | 6 + .../types/conversation_profile.py | 92 + .../cloud/dialogflow_v2/types/participant.py | 173 +- .../cloud/dialogflow_v2/types/session.py | 25 +- .../cloud/dialogflow_v2beta1/__init__.py | 2 + .../conversation_profiles/async_client.py | 6 - .../services/conversation_profiles/client.py | 22 - .../services/conversations/async_client.py | 4 - .../services/conversations/client.py | 22 - .../services/participants/async_client.py | 10 +- .../services/participants/client.py | 10 +- .../dialogflow_v2beta1/types/__init__.py | 2 + .../dialogflow_v2beta1/types/audio_config.py | 2 +- .../cloud/dialogflow_v2beta1/types/ces_app.py | 26 + .../dialogflow_v2beta1/types/conversation.py | 6 + .../types/conversation_profile.py | 136 +- .../dialogflow_v2beta1/types/participant.py | 278 +- .../cloud/dialogflow_v2beta1/types/session.py | 25 +- .../test_conversation_profiles.py | 28 + .../gapic/dialogflow_v2/test_conversations.py | 14 + .../test_generator_evaluations.py | 7 +- .../gapic/dialogflow_v2/test_generators.py | 18 +- .../test_conversation_profiles.py | 152 +- .../dialogflow_v2beta1/test_conversations.py | 190 +- .../test_generator_evaluations.py | 7 +- .../dialogflow_v2beta1/test_generators.py | 18 +- .../acl_config_service.rst | 6 + .../assistant_service.rst | 10 + .../cmek_config_service.rst | 6 + .../identity_mapping_store_service.rst | 10 + .../license_config_service.rst | 10 + .../docs/discoveryengine_v1beta/services_.rst | 7 + .../user_license_service.rst | 10 + .../user_store_service.rst | 6 + .../google/cloud/discoveryengine/__init__.py | 241 +- .../cloud/discoveryengine_v1beta/__init__.py | 210 +- .../gapic_metadata.json | 673 + .../services/acl_config_service/__init__.py | 22 + .../acl_config_service/async_client.py | 702 + .../services/acl_config_service/client.py | 1143 ++ .../acl_config_service/transports/README.rst | 10 + .../acl_config_service/transports/__init__.py | 36 + .../acl_config_service/transports/base.py | 240 + .../acl_config_service/transports/grpc.py | 447 + .../transports/grpc_asyncio.py | 494 + .../acl_config_service/transports/rest.py | 1081 ++ .../transports/rest_base.py | 407 + .../services/assistant_service/__init__.py | 22 + .../assistant_service/async_client.py | 1194 ++ .../services/assistant_service/client.py | 1762 ++ .../services/assistant_service/pagers.py | 197 + .../assistant_service/transports/README.rst | 10 + .../assistant_service/transports/__init__.py | 36 + .../assistant_service/transports/base.py | 314 + .../assistant_service/transports/grpc.py | 561 + .../transports/grpc_asyncio.py | 642 + .../assistant_service/transports/rest.py | 1875 ++ .../assistant_service/transports/rest_base.py | 619 + .../services/cmek_config_service/__init__.py | 22 + .../cmek_config_service/async_client.py | 1028 ++ .../services/cmek_config_service/client.py | 1515 ++ .../cmek_config_service/transports/README.rst | 10 + .../transports/__init__.py | 36 + .../cmek_config_service/transports/base.py | 278 + .../cmek_config_service/transports/grpc.py | 528 + .../transports/grpc_asyncio.py | 584 + .../cmek_config_service/transports/rest.py | 1702 ++ .../transports/rest_base.py | 510 + .../completion_service/async_client.py | 98 + .../services/completion_service/client.py | 96 + .../completion_service/transports/base.py | 25 +- .../completion_service/transports/grpc.py | 33 + .../transports/grpc_asyncio.py | 38 + .../completion_service/transports/rest.py | 241 + .../transports/rest_base.py | 69 + .../services/control_service/async_client.py | 10 +- .../services/control_service/client.py | 34 +- .../control_service/transports/base.py | 6 +- .../control_service/transports/rest_base.py | 12 + .../async_client.py | 112 + .../conversational_search_service/client.py | 131 + .../transports/base.py | 23 +- .../transports/grpc.py | 35 + .../transports/grpc_asyncio.py | 40 + .../transports/rest.py | 221 + .../transports/rest_base.py | 79 + .../data_store_service/async_client.py | 18 + .../services/data_store_service/client.py | 93 + .../data_store_service/transports/base.py | 6 +- .../data_store_service/transports/rest.py | 12 + .../transports/rest_base.py | 12 + .../services/document_service/async_client.py | 2 +- .../services/document_service/client.py | 2 +- .../document_service/transports/base.py | 6 +- .../document_service/transports/rest.py | 12 + .../document_service/transports/rest_base.py | 12 + .../services/engine_service/async_client.py | 339 +- .../services/engine_service/client.py | 418 +- .../engine_service/transports/base.py | 36 +- .../engine_service/transports/grpc.py | 88 +- .../engine_service/transports/grpc_asyncio.py | 98 +- .../engine_service/transports/rest.py | 582 + .../engine_service/transports/rest_base.py | 118 + .../evaluation_service/async_client.py | 8 +- .../services/evaluation_service/client.py | 8 +- .../evaluation_service/transports/base.py | 7 +- .../evaluation_service/transports/rest.py | 12 + .../transports/rest_base.py | 12 + .../transports/base.py | 6 +- .../transports/rest_base.py | 12 + .../__init__.py | 22 + .../async_client.py | 1418 ++ .../identity_mapping_store_service/client.py | 1917 ++ .../identity_mapping_store_service/pagers.py | 383 + .../transports/README.rst | 10 + .../transports/__init__.py | 39 + .../transports/base.py | 333 + .../transports/grpc.py | 627 + .../transports/grpc_asyncio.py | 697 + .../transports/rest.py | 2431 +++ .../transports/rest_base.py | 694 + .../license_config_service/__init__.py | 22 + .../license_config_service/async_client.py | 1405 ++ .../services/license_config_service/client.py | 1863 ++ .../services/license_config_service/pagers.py | 204 + .../transports/README.rst | 10 + .../transports/__init__.py | 36 + .../license_config_service/transports/base.py | 317 + .../license_config_service/transports/grpc.py | 582 + .../transports/grpc_asyncio.py | 646 + .../license_config_service/transports/rest.py | 2024 +++ .../transports/rest_base.py | 633 + .../services/project_service/async_client.py | 6 + .../services/project_service/client.py | 44 + .../project_service/transports/base.py | 6 +- .../project_service/transports/rest.py | 12 + .../project_service/transports/rest_base.py | 12 + .../services/rank_service/transports/base.py | 6 +- .../rank_service/transports/rest_base.py | 12 + .../recommendation_service/transports/base.py | 6 +- .../transports/rest_base.py | 12 + .../sample_query_service/transports/base.py | 6 +- .../sample_query_service/transports/rest.py | 12 + .../transports/rest_base.py | 12 + .../transports/base.py | 6 +- .../transports/rest_base.py | 12 + .../schema_service/transports/base.py | 6 +- .../schema_service/transports/rest.py | 12 + .../schema_service/transports/rest_base.py | 12 + .../search_service/transports/base.py | 7 +- .../search_service/transports/rest_base.py | 12 + .../search_tuning_service/transports/base.py | 6 +- .../search_tuning_service/transports/rest.py | 12 + .../transports/rest_base.py | 12 + .../serving_config_service/async_client.py | 264 +- .../services/serving_config_service/client.py | 258 +- .../serving_config_service/transports/base.py | 38 +- .../serving_config_service/transports/grpc.py | 68 + .../transports/grpc_asyncio.py | 80 + .../serving_config_service/transports/rest.py | 370 + .../transports/rest_base.py | 137 + .../services/session_service/async_client.py | 4 + .../services/session_service/client.py | 28 + .../session_service/transports/base.py | 7 +- .../session_service/transports/rest_base.py | 12 + .../transports/base.py | 6 +- .../transports/rest.py | 12 + .../transports/rest_base.py | 16 + .../user_event_service/async_client.py | 1 + .../services/user_event_service/client.py | 1 + .../user_event_service/transports/base.py | 7 +- .../user_event_service/transports/rest.py | 12 + .../transports/rest_base.py | 17 + .../services/user_license_service/__init__.py | 22 + .../user_license_service/async_client.py | 862 + .../services/user_license_service/client.py | 1323 ++ .../services/user_license_service/pagers.py | 199 + .../transports/README.rst | 10 + .../transports/__init__.py | 36 + .../user_license_service/transports/base.py | 265 + .../user_license_service/transports/grpc.py | 503 + .../transports/grpc_asyncio.py | 552 + .../user_license_service/transports/rest.py | 1507 ++ .../transports/rest_base.py | 456 + .../services/user_store_service/__init__.py | 22 + .../user_store_service/async_client.py | 734 + .../services/user_store_service/client.py | 1195 ++ .../user_store_service/transports/README.rst | 10 + .../user_store_service/transports/__init__.py | 36 + .../user_store_service/transports/base.py | 241 + .../user_store_service/transports/grpc.py | 446 + .../transports/grpc_asyncio.py | 491 + .../user_store_service/transports/rest.py | 1089 ++ .../transports/rest_base.py | 408 + .../discoveryengine_v1beta/types/__init__.py | 196 + .../types/acl_config.py | 58 + .../types/acl_config_service.py | 69 + .../types/agent_gateway_setting.py | 67 + .../discoveryengine_v1beta/types/answer.py | 207 +- .../types/assist_answer.py | 730 + .../discoveryengine_v1beta/types/assistant.py | 391 + .../types/assistant_service.py | 563 + .../discoveryengine_v1beta/types/chunk.py | 99 +- .../types/cmek_config_service.py | 344 + .../discoveryengine_v1beta/types/common.py | 348 + .../types/completion_service.py | 216 +- .../discoveryengine_v1beta/types/control.py | 193 +- .../types/conversational_search_service.py | 291 +- .../types/data_store.py | 387 +- .../types/data_store_service.py | 29 + .../discoveryengine_v1beta/types/document.py | 115 +- .../types/document_processing_config.py | 65 +- .../types/document_service.py | 2 +- .../discoveryengine_v1beta/types/engine.py | 570 +- .../types/evaluation.py | 4 +- .../types/evaluation_service.py | 25 +- .../discoveryengine_v1beta/types/feedback.py | 227 + .../types/grounded_generation_service.py | 350 +- .../discoveryengine_v1beta/types/grounding.py | 18 + .../types/identity_mapping_store.py | 128 + .../types/identity_mapping_store_service.py | 488 + .../types/import_config.py | 40 +- .../types/license_config.py | 166 + .../types/license_config_service.py | 348 + .../discoveryengine_v1beta/types/logging.py | 53 + .../discoveryengine_v1beta/types/project.py | 350 + .../types/project_service.py | 30 + .../types/purge_config.py | 13 +- .../types/rank_service.py | 10 +- .../types/recommendation_service.py | 4 +- .../discoveryengine_v1beta/types/safety.py | 152 + .../types/search_service.py | 782 +- .../types/serving_config.py | 101 +- .../types/serving_config_service.py | 51 + .../discoveryengine_v1beta/types/session.py | 36 + .../types/site_search_engine.py | 9 +- .../types/site_search_engine_service.py | 19 +- .../types/user_event.py | 65 +- .../types/user_event_service.py | 17 +- .../types/user_license.py | 152 + .../types/user_license_service.py | 329 + .../types/user_store.py | 94 + .../types/user_store_service.py | 75 + ...cl_config_service_get_acl_config_async.py} | 18 +- ..._acl_config_service_get_acl_config_sync.py | 53 + ..._config_service_update_acl_config_async.py | 51 + ...l_config_service_update_acl_config_sync.py | 51 + ...ssistant_service_create_assistant_async.py | 58 + ...assistant_service_create_assistant_sync.py | 58 + ...ssistant_service_delete_assistant_async.py | 50 + ...assistant_service_delete_assistant_sync.py | 50 + ...d_assistant_service_get_assistant_async.py | 53 + ...ed_assistant_service_get_assistant_sync.py | 53 + ...assistant_service_list_assistants_async.py | 54 + ..._assistant_service_list_assistants_sync.py | 54 + ...d_assistant_service_stream_assist_async.py | 54 + ...ed_assistant_service_stream_assist_sync.py | 54 + ...ssistant_service_update_assistant_async.py | 56 + ...assistant_service_update_assistant_sync.py | 56 + ...onfig_service_delete_cmek_config_async.py} | 22 +- ...config_service_delete_cmek_config_sync.py} | 22 +- ...ek_config_service_get_cmek_config_async.py | 53 + ...mek_config_service_get_cmek_config_sync.py | 53 + ..._config_service_list_cmek_configs_async.py | 53 + ...k_config_service_list_cmek_configs_sync.py | 53 + ...config_service_update_cmek_config_async.py | 61 + ..._config_service_update_cmek_config_sync.py | 61 + ...pletion_service_remove_suggestion_async.py | 55 + ...mpletion_service_remove_suggestion_sync.py | 55 + ...ed_control_service_create_control_async.py | 4 +- ...ted_control_service_create_control_sync.py | 4 +- ...ed_control_service_update_control_async.py | 4 +- ...ted_control_service_update_control_sync.py | 4 +- ...earch_service_stream_answer_query_async.py | 58 + ...search_service_stream_answer_query_sync.py | 58 + ...a_store_service_create_data_store_async.py | 1 + ...ta_store_service_create_data_store_sync.py | 1 + ...ated_engine_service_create_engine_async.py | 2 +- ...rated_engine_service_create_engine_sync.py | 2 +- ...ted_engine_service_get_iam_policy_async.py | 55 + ...ated_engine_service_get_iam_policy_sync.py | 55 + ...ted_engine_service_set_iam_policy_async.py | 55 + ...ated_engine_service_set_iam_policy_sync.py | 55 + ...ated_engine_service_update_engine_async.py | 2 +- ...rated_engine_service_update_engine_sync.py | 2 +- ...luation_service_create_evaluation_async.py | 3 - ...aluation_service_create_evaluation_sync.py | 3 - ...ice_create_identity_mapping_store_async.py | 55 + ...vice_create_identity_mapping_store_sync.py | 55 + ...ice_delete_identity_mapping_store_async.py | 57 + ...vice_delete_identity_mapping_store_sync.py | 57 + ...ervice_get_identity_mapping_store_async.py | 53 + ...service_get_identity_mapping_store_sync.py | 53 + ..._service_import_identity_mappings_async.py | 57 + ...e_service_import_identity_mappings_sync.py | 57 + ...vice_list_identity_mapping_stores_async.py | 54 + ...vice_list_identity_mapping_stores_sync.py} | 23 +- ...re_service_list_identity_mappings_async.py | 54 + ...ore_service_list_identity_mappings_sync.py | 54 + ...e_service_purge_identity_mappings_async.py | 57 + ...re_service_purge_identity_mappings_sync.py | 57 + ...fig_service_create_license_config_async.py | 59 + ...nfig_service_create_license_config_sync.py | 59 + ...service_distribute_license_config_async.py | 56 + ..._service_distribute_license_config_sync.py | 56 + ...config_service_get_license_config_async.py | 53 + ..._config_service_get_license_config_sync.py | 53 + ...nfig_service_list_license_configs_async.py | 54 + ...onfig_service_list_license_configs_sync.py | 54 + ...ig_service_retract_license_config_async.py | 54 + ...fig_service_retract_license_config_sync.py | 54 + ...fig_service_update_license_config_async.py | 58 + ...nfig_service_update_license_config_sync.py | 58 + ...fig_service_create_serving_config_async.py | 60 + ...nfig_service_create_serving_config_sync.py | 60 + ...fig_service_delete_serving_config_async.py | 50 + ...nfig_service_delete_serving_config_sync.py | 50 + ...fig_service_update_serving_config_async.py | 2 +- ...nfig_service_update_serving_config_sync.py | 2 +- ...ervice_batch_update_user_licenses_async.py | 61 + ...service_batch_update_user_licenses_sync.py | 61 + ..._list_license_configs_usage_stats_async.py | 53 + ...e_list_license_configs_usage_stats_sync.py | 53 + ...icense_service_list_user_licenses_async.py | 54 + ...license_service_list_user_licenses_sync.py | 54 + ...user_store_service_get_user_store_async.py | 53 + ..._user_store_service_get_user_store_sync.py | 53 + ...r_store_service_update_user_store_async.py | 51 + ...er_store_service_update_user_store_sync.py | 51 + ...a_google.cloud.discoveryengine.v1beta.json | 14440 ++++++++++----- .../google-cloud-discoveryengine/setup.py | 1 + .../testing/constraints-3.10.txt | 1 + .../testing/constraints-3.11.txt | 1 + .../testing/constraints-3.12.txt | 1 + .../testing/constraints-3.13.txt | 1 + .../testing/constraints-3.14.txt | 1 + .../test_acl_config_service.py | 4265 +++++ .../test_assistant_service.py | 7679 ++++++++ .../test_cmek_config_service.py | 6071 +++++++ .../test_completion_service.py | 640 +- .../test_control_service.py | 160 +- .../test_conversational_search_service.py | 1099 +- .../test_data_store_service.py | 453 +- .../test_document_service.py | 61 +- .../test_engine_service.py | 4375 +++-- .../test_evaluation_service.py | 77 +- .../test_grounded_generation_service.py | 30 +- .../test_identity_mapping_store_service.py | 8759 +++++++++ .../test_license_config_service.py | 8290 +++++++++ .../test_project_service.py | 88 +- .../test_rank_service.py | 30 +- .../test_recommendation_service.py | 33 +- .../test_sample_query_service.py | 30 +- .../test_sample_query_set_service.py | 30 +- .../test_schema_service.py | 30 +- .../test_search_service.py | 80 +- .../test_search_tuning_service.py | 30 +- .../test_serving_config_service.py | 3990 +++-- .../test_session_service.py | 433 +- .../test_site_search_engine_service.py | 30 +- .../test_user_event_service.py | 81 +- .../test_user_license_service.py | 5384 ++++++ .../test_user_store_service.py | 4514 +++++ .../cloud/network_management/__init__.py | 4 + .../cloud/network_management_v1/__init__.py | 4 + .../network_management_v1/types/__init__.py | 4 + .../types/connectivity_test.py | 18 + .../network_management_v1/types/trace.py | 94 + .../test_reachability_service.py | 16 + .../types/security_profile_group.py | 3 +- .../types/agent_gateway.py | 2 +- .../google/cloud/oracledatabase/__init__.py | 12 +- .../cloud/oracledatabase_v1/__init__.py | 12 +- .../oracledatabase_v1/gapic_metadata.json | 75 +- .../services/oracle_database/async_client.py | 804 +- .../services/oracle_database/client.py | 799 +- .../oracle_database/transports/base.py | 84 +- .../oracle_database/transports/grpc.py | 160 +- .../transports/grpc_asyncio.py | 185 +- .../oracle_database/transports/rest.py | 1519 +- .../oracle_database/transports/rest_base.py | 263 +- .../cloud/oracledatabase_v1/types/__init__.py | 12 +- .../oracledatabase_v1/types/exadata_infra.py | 63 + .../types/exascale_db_storage_vault.py | 9 + .../types/goldengate_connection_type.py | 16 - .../goldengate_deployment_environment.py | 16 - .../types/goldengate_deployment_type.py | 17 - .../types/goldengate_deployment_version.py | 17 - .../oracledatabase_v1/types/vm_cluster.py | 32 + ...ale_cloud_exadata_infrastructure_async.py} | 19 +- ...cale_cloud_exadata_infrastructure_sync.py} | 17 +- ...tadata_google.cloud.oracledatabase.v1.json | 839 +- .../oracledatabase_v1/test_oracle_database.py | 14764 +++++++--------- .../types/data_object_search_service.py | 7 +- .../types/vectorsearch_service.py | 79 + .../types/data_object_search_service.py | 7 +- .../types/vectorsearch_service.py | 79 + .../test_vector_search_service.py | 17 +- .../test_vector_search_service.py | 17 +- 531 files changed, 159517 insertions(+), 20194 deletions(-) create mode 100644 packages/google-ads-datamanager/google/ads/datamanager_v1/types/ad_event.py create mode 100644 packages/google-ads-datamanager/google/ads/datamanager_v1/types/viewability_info.py create mode 100644 packages/google-ads-datamanager/samples/generated_samples/datamanager_v1_generated_ingestion_service_ingest_ad_events_async.py create mode 100644 packages/google-ads-datamanager/samples/generated_samples/datamanager_v1_generated_ingestion_service_ingest_ad_events_sync.py create mode 100644 packages/google-cloud-chronicle/docs/chronicle_v1/rule_execution_error_service.rst create mode 100644 packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_execution_error_service/__init__.py create mode 100644 packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_execution_error_service/async_client.py create mode 100644 packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_execution_error_service/client.py create mode 100644 packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_execution_error_service/pagers.py create mode 100644 packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_execution_error_service/transports/README.rst create mode 100644 packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_execution_error_service/transports/__init__.py create mode 100644 packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_execution_error_service/transports/base.py create mode 100644 packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_execution_error_service/transports/grpc.py create mode 100644 packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_execution_error_service/transports/grpc_asyncio.py create mode 100644 packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_execution_error_service/transports/rest.py create mode 100644 packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_execution_error_service/transports/rest_base.py create mode 100644 packages/google-cloud-chronicle/google/cloud/chronicle_v1/types/rule_execution_error.py create mode 100644 packages/google-cloud-chronicle/samples/generated_samples/chronicle_v1_generated_reference_list_service_verify_reference_list_async.py create mode 100644 packages/google-cloud-chronicle/samples/generated_samples/chronicle_v1_generated_reference_list_service_verify_reference_list_sync.py create mode 100644 packages/google-cloud-chronicle/samples/generated_samples/chronicle_v1_generated_rule_execution_error_service_list_rule_execution_errors_async.py create mode 100644 packages/google-cloud-chronicle/samples/generated_samples/chronicle_v1_generated_rule_execution_error_service_list_rule_execution_errors_sync.py create mode 100644 packages/google-cloud-chronicle/samples/generated_samples/chronicle_v1_generated_rule_service_verify_rule_text_async.py create mode 100644 packages/google-cloud-chronicle/samples/generated_samples/chronicle_v1_generated_rule_service_verify_rule_text_sync.py create mode 100644 packages/google-cloud-chronicle/tests/unit/gapic/chronicle_v1/test_rule_execution_error_service.py rename packages/{google-cloud-oracledatabase/samples/generated_samples/oracledatabase_v1_generated_oracle_database_get_goldengate_deployment_type_async.py => google-cloud-dataform/samples/generated_samples/dataform_v1beta1_generated_dataform_delete_folder_tree_async.py} (71%) rename packages/{google-cloud-oracledatabase/samples/generated_samples/oracledatabase_v1_generated_oracle_database_get_goldengate_connection_type_sync.py => google-cloud-dataform/samples/generated_samples/dataform_v1beta1_generated_dataform_delete_folder_tree_sync.py} (72%) create mode 100644 packages/google-cloud-dataform/samples/generated_samples/dataform_v1beta1_generated_dataform_delete_repository_long_running_async.py create mode 100644 packages/google-cloud-dataform/samples/generated_samples/dataform_v1beta1_generated_dataform_delete_repository_long_running_sync.py create mode 100644 packages/google-cloud-dataform/samples/generated_samples/dataform_v1beta1_generated_dataform_delete_team_folder_tree_async.py create mode 100644 packages/google-cloud-dataform/samples/generated_samples/dataform_v1beta1_generated_dataform_delete_team_folder_tree_sync.py create mode 100644 packages/google-cloud-discoveryengine/docs/discoveryengine_v1beta/acl_config_service.rst create mode 100644 packages/google-cloud-discoveryengine/docs/discoveryengine_v1beta/assistant_service.rst create mode 100644 packages/google-cloud-discoveryengine/docs/discoveryengine_v1beta/cmek_config_service.rst create mode 100644 packages/google-cloud-discoveryengine/docs/discoveryengine_v1beta/identity_mapping_store_service.rst create mode 100644 packages/google-cloud-discoveryengine/docs/discoveryengine_v1beta/license_config_service.rst create mode 100644 packages/google-cloud-discoveryengine/docs/discoveryengine_v1beta/user_license_service.rst create mode 100644 packages/google-cloud-discoveryengine/docs/discoveryengine_v1beta/user_store_service.rst create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/acl_config_service/__init__.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/acl_config_service/async_client.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/acl_config_service/client.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/acl_config_service/transports/README.rst create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/acl_config_service/transports/__init__.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/acl_config_service/transports/base.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/acl_config_service/transports/grpc.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/acl_config_service/transports/grpc_asyncio.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/acl_config_service/transports/rest.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/acl_config_service/transports/rest_base.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/assistant_service/__init__.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/assistant_service/async_client.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/assistant_service/client.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/assistant_service/pagers.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/assistant_service/transports/README.rst create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/assistant_service/transports/__init__.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/assistant_service/transports/base.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/assistant_service/transports/grpc.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/assistant_service/transports/grpc_asyncio.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/assistant_service/transports/rest.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/assistant_service/transports/rest_base.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/cmek_config_service/__init__.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/cmek_config_service/async_client.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/cmek_config_service/client.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/cmek_config_service/transports/README.rst create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/cmek_config_service/transports/__init__.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/cmek_config_service/transports/base.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/cmek_config_service/transports/grpc.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/cmek_config_service/transports/grpc_asyncio.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/cmek_config_service/transports/rest.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/cmek_config_service/transports/rest_base.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/identity_mapping_store_service/__init__.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/identity_mapping_store_service/async_client.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/identity_mapping_store_service/client.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/identity_mapping_store_service/pagers.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/identity_mapping_store_service/transports/README.rst create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/identity_mapping_store_service/transports/__init__.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/identity_mapping_store_service/transports/base.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/identity_mapping_store_service/transports/grpc.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/identity_mapping_store_service/transports/grpc_asyncio.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/identity_mapping_store_service/transports/rest.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/identity_mapping_store_service/transports/rest_base.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/license_config_service/__init__.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/license_config_service/async_client.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/license_config_service/client.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/license_config_service/pagers.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/license_config_service/transports/README.rst create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/license_config_service/transports/__init__.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/license_config_service/transports/base.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/license_config_service/transports/grpc.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/license_config_service/transports/grpc_asyncio.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/license_config_service/transports/rest.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/license_config_service/transports/rest_base.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/user_license_service/__init__.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/user_license_service/async_client.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/user_license_service/client.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/user_license_service/pagers.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/user_license_service/transports/README.rst create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/user_license_service/transports/__init__.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/user_license_service/transports/base.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/user_license_service/transports/grpc.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/user_license_service/transports/grpc_asyncio.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/user_license_service/transports/rest.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/user_license_service/transports/rest_base.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/user_store_service/__init__.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/user_store_service/async_client.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/user_store_service/client.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/user_store_service/transports/README.rst create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/user_store_service/transports/__init__.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/user_store_service/transports/base.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/user_store_service/transports/grpc.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/user_store_service/transports/grpc_asyncio.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/user_store_service/transports/rest.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/user_store_service/transports/rest_base.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/acl_config.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/acl_config_service.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/agent_gateway_setting.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/assist_answer.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/assistant.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/assistant_service.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/cmek_config_service.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/feedback.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/identity_mapping_store.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/identity_mapping_store_service.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/license_config.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/license_config_service.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/logging.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/safety.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/user_license.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/user_license_service.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/user_store.py create mode 100644 packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/types/user_store_service.py rename packages/{google-cloud-oracledatabase/samples/generated_samples/oracledatabase_v1_generated_oracle_database_get_goldengate_deployment_type_sync.py => google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_acl_config_service_get_acl_config_async.py} (72%) create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_acl_config_service_get_acl_config_sync.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_acl_config_service_update_acl_config_async.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_acl_config_service_update_acl_config_sync.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_assistant_service_create_assistant_async.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_assistant_service_create_assistant_sync.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_assistant_service_delete_assistant_async.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_assistant_service_delete_assistant_sync.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_assistant_service_get_assistant_async.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_assistant_service_get_assistant_sync.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_assistant_service_list_assistants_async.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_assistant_service_list_assistants_sync.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_assistant_service_stream_assist_async.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_assistant_service_stream_assist_sync.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_assistant_service_update_assistant_async.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_assistant_service_update_assistant_sync.py rename packages/{google-cloud-oracledatabase/samples/generated_samples/oracledatabase_v1_generated_oracle_database_get_goldengate_deployment_environment_async.py => google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_cmek_config_service_delete_cmek_config_async.py} (69%) rename packages/{google-cloud-oracledatabase/samples/generated_samples/oracledatabase_v1_generated_oracle_database_get_goldengate_deployment_environment_sync.py => google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_cmek_config_service_delete_cmek_config_sync.py} (70%) create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_cmek_config_service_get_cmek_config_async.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_cmek_config_service_get_cmek_config_sync.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_cmek_config_service_list_cmek_configs_async.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_cmek_config_service_list_cmek_configs_sync.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_cmek_config_service_update_cmek_config_async.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_cmek_config_service_update_cmek_config_sync.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_completion_service_remove_suggestion_async.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_completion_service_remove_suggestion_sync.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_conversational_search_service_stream_answer_query_async.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_conversational_search_service_stream_answer_query_sync.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_engine_service_get_iam_policy_async.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_engine_service_get_iam_policy_sync.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_engine_service_set_iam_policy_async.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_engine_service_set_iam_policy_sync.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_identity_mapping_store_service_create_identity_mapping_store_async.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_identity_mapping_store_service_create_identity_mapping_store_sync.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_identity_mapping_store_service_delete_identity_mapping_store_async.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_identity_mapping_store_service_delete_identity_mapping_store_sync.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_identity_mapping_store_service_get_identity_mapping_store_async.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_identity_mapping_store_service_get_identity_mapping_store_sync.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_identity_mapping_store_service_import_identity_mappings_async.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_identity_mapping_store_service_import_identity_mappings_sync.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_identity_mapping_store_service_list_identity_mapping_stores_async.py rename packages/{google-cloud-oracledatabase/samples/generated_samples/oracledatabase_v1_generated_oracle_database_get_goldengate_deployment_version_async.py => google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_identity_mapping_store_service_list_identity_mapping_stores_sync.py} (66%) create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_identity_mapping_store_service_list_identity_mappings_async.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_identity_mapping_store_service_list_identity_mappings_sync.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_identity_mapping_store_service_purge_identity_mappings_async.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_identity_mapping_store_service_purge_identity_mappings_sync.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_license_config_service_create_license_config_async.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_license_config_service_create_license_config_sync.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_license_config_service_distribute_license_config_async.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_license_config_service_distribute_license_config_sync.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_license_config_service_get_license_config_async.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_license_config_service_get_license_config_sync.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_license_config_service_list_license_configs_async.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_license_config_service_list_license_configs_sync.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_license_config_service_retract_license_config_async.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_license_config_service_retract_license_config_sync.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_license_config_service_update_license_config_async.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_license_config_service_update_license_config_sync.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_serving_config_service_create_serving_config_async.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_serving_config_service_create_serving_config_sync.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_serving_config_service_delete_serving_config_async.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_serving_config_service_delete_serving_config_sync.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_user_license_service_batch_update_user_licenses_async.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_user_license_service_batch_update_user_licenses_sync.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_user_license_service_list_license_configs_usage_stats_async.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_user_license_service_list_license_configs_usage_stats_sync.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_user_license_service_list_user_licenses_async.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_user_license_service_list_user_licenses_sync.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_user_store_service_get_user_store_async.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_user_store_service_get_user_store_sync.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_user_store_service_update_user_store_async.py create mode 100644 packages/google-cloud-discoveryengine/samples/generated_samples/discoveryengine_v1beta_generated_user_store_service_update_user_store_sync.py create mode 100644 packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1beta/test_acl_config_service.py create mode 100644 packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1beta/test_assistant_service.py create mode 100644 packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1beta/test_cmek_config_service.py create mode 100644 packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1beta/test_identity_mapping_store_service.py create mode 100644 packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1beta/test_license_config_service.py create mode 100644 packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1beta/test_user_license_service.py create mode 100644 packages/google-cloud-discoveryengine/tests/unit/gapic/discoveryengine_v1beta/test_user_store_service.py rename packages/google-cloud-oracledatabase/samples/generated_samples/{oracledatabase_v1_generated_oracle_database_get_goldengate_connection_type_async.py => oracledatabase_v1_generated_oracle_database_configure_exascale_cloud_exadata_infrastructure_async.py} (70%) rename packages/google-cloud-oracledatabase/samples/generated_samples/{oracledatabase_v1_generated_oracle_database_get_goldengate_deployment_version_sync.py => oracledatabase_v1_generated_oracle_database_configure_exascale_cloud_exadata_infrastructure_sync.py} (71%) diff --git a/librarian.yaml b/librarian.yaml index 2f3a4a2cc90a..eb38359a0aa8 100644 --- a/librarian.yaml +++ b/librarian.yaml @@ -16,8 +16,8 @@ version: v0.22.0 repo: googleapis/google-cloud-python sources: googleapis: - commit: f93e046328794785ad89869f00c0358dfcff2c35 - sha256: 415249f584d57e5a2298c36ae9ff71563403112dee04ac961023a1b0098404d2 + commit: e57bae6efbd075a925978a79bb9b997beb4ecc19 + sha256: 762523e55a4cd9f57c7e5a952dd76ca6041c0e1dd405c14b1d6cfb165e4730b1 default: output: packages tag_format: '{name}-v{version}' diff --git a/packages/google-ads-datamanager/google/ads/datamanager/__init__.py b/packages/google-ads-datamanager/google/ads/datamanager/__init__.py index 4c2ea0af79c2..a88f6c4f0ad2 100644 --- a/packages/google-ads-datamanager/google/ads/datamanager/__init__.py +++ b/packages/google-ads-datamanager/google/ads/datamanager/__init__.py @@ -54,6 +54,16 @@ from google.ads.datamanager_v1.services.user_list_service.client import ( UserListServiceClient, ) +from google.ads.datamanager_v1.types.ad_event import ( + AdEvent, + AdFormat, + AdPlacement, + AdType, + AttributionHint, + Platform, + PlatformType, + TargetingType, +) from google.ads.datamanager_v1.types.age_range import AgeRange from google.ads.datamanager_v1.types.audience import ( AudienceMember, @@ -75,6 +85,7 @@ from google.ads.datamanager_v1.types.encrypted_user_id import EncryptedUserId from google.ads.datamanager_v1.types.encryption_info import ( AwsWrappedKeyInfo, + CoordinatorKeyInfo, EncryptionInfo, GcpWrappedKeyInfo, ) @@ -91,6 +102,8 @@ from google.ads.datamanager_v1.types.gender import Gender from google.ads.datamanager_v1.types.ingestion_service import ( Encoding, + IngestAdEventsRequest, + IngestAdEventsResponse, IngestAudienceMembersRequest, IngestAudienceMembersResponse, IngestEventsRequest, @@ -110,7 +123,10 @@ from google.ads.datamanager_v1.types.partner_link_service import ( CreatePartnerLinkRequest, DeletePartnerLinkRequest, + FeatureSet, + PartnerCustomerAccount, PartnerLink, + PartnerLinkMetadata, SearchPartnerLinksRequest, SearchPartnerLinksResponse, ) @@ -199,6 +215,11 @@ UserProperties, UserProperty, ) +from google.ads.datamanager_v1.types.viewability_info import ( + MediaQuartile, + ViewabilityInfo, + ViewType, +) __all__ = ( "IngestionServiceClient", @@ -213,6 +234,14 @@ "UserListGlobalLicenseServiceAsyncClient", "UserListServiceClient", "UserListServiceAsyncClient", + "AdEvent", + "AdFormat", + "AdPlacement", + "AdType", + "AttributionHint", + "Platform", + "PlatformType", + "TargetingType", "AgeRange", "AudienceMember", "CompositeData", @@ -232,6 +261,7 @@ "DeviceInfo", "EncryptedUserId", "AwsWrappedKeyInfo", + "CoordinatorKeyInfo", "EncryptionInfo", "GcpWrappedKeyInfo", "ErrorReason", @@ -243,6 +273,8 @@ "EventSource", "ExperimentalField", "Gender", + "IngestAdEventsRequest", + "IngestAdEventsResponse", "IngestAudienceMembersRequest", "IngestAudienceMembersResponse", "IngestEventsRequest", @@ -259,9 +291,12 @@ "MatchRateRange", "CreatePartnerLinkRequest", "DeletePartnerLinkRequest", + "PartnerCustomerAccount", "PartnerLink", + "PartnerLinkMetadata", "SearchPartnerLinksRequest", "SearchPartnerLinksResponse", + "FeatureSet", "ErrorCount", "ErrorInfo", "WarningCount", @@ -315,4 +350,7 @@ "UserProperty", "CustomerType", "CustomerValueBucket", + "ViewabilityInfo", + "MediaQuartile", + "ViewType", ) diff --git a/packages/google-ads-datamanager/google/ads/datamanager_v1/__init__.py b/packages/google-ads-datamanager/google/ads/datamanager_v1/__init__.py index 090ecb7224b2..f09a49051ab0 100644 --- a/packages/google-ads-datamanager/google/ads/datamanager_v1/__init__.py +++ b/packages/google-ads-datamanager/google/ads/datamanager_v1/__init__.py @@ -47,6 +47,16 @@ UserListServiceAsyncClient, UserListServiceClient, ) +from .types.ad_event import ( + AdEvent, + AdFormat, + AdPlacement, + AdType, + AttributionHint, + Platform, + PlatformType, + TargetingType, +) from .types.age_range import AgeRange from .types.audience import ( AudienceMember, @@ -62,7 +72,12 @@ from .types.destination import Destination, Product, ProductAccount from .types.device_info import DeviceInfo from .types.encrypted_user_id import EncryptedUserId -from .types.encryption_info import AwsWrappedKeyInfo, EncryptionInfo, GcpWrappedKeyInfo +from .types.encryption_info import ( + AwsWrappedKeyInfo, + CoordinatorKeyInfo, + EncryptionInfo, + GcpWrappedKeyInfo, +) from .types.error import ErrorReason from .types.event import ( AdIdentifiers, @@ -76,6 +91,8 @@ from .types.gender import Gender from .types.ingestion_service import ( Encoding, + IngestAdEventsRequest, + IngestAdEventsResponse, IngestAudienceMembersRequest, IngestAudienceMembersResponse, IngestEventsRequest, @@ -95,7 +112,10 @@ from .types.partner_link_service import ( CreatePartnerLinkRequest, DeletePartnerLinkRequest, + FeatureSet, + PartnerCustomerAccount, PartnerLink, + PartnerLinkMetadata, SearchPartnerLinksRequest, SearchPartnerLinksResponse, ) @@ -165,6 +185,7 @@ UserProperties, UserProperty, ) +from .types.viewability_info import MediaQuartile, ViewabilityInfo, ViewType if hasattr(api_core, "check_python_version") and hasattr( api_core, "check_dependency_versions" @@ -256,9 +277,14 @@ def _get_version(dependency_name): "UserListDirectLicenseServiceAsyncClient", "UserListGlobalLicenseServiceAsyncClient", "UserListServiceAsyncClient", + "AdEvent", + "AdFormat", "AdIdentifiers", + "AdPlacement", + "AdType", "AddressInfo", "AgeRange", + "AttributionHint", "AudienceMember", "AwsWrappedKeyInfo", "Baseline", @@ -267,6 +293,7 @@ def _get_version(dependency_name): "Consent", "ConsentStatus", "ContactIdInfo", + "CoordinatorKeyInfo", "CreatePartnerLinkRequest", "CreateUserListDirectLicenseRequest", "CreateUserListGlobalLicenseRequest", @@ -290,11 +317,14 @@ def _get_version(dependency_name): "EventParameter", "EventSource", "ExperimentalField", + "FeatureSet", "GcpWrappedKeyInfo", "Gender", "GetUserListDirectLicenseRequest", "GetUserListGlobalLicenseRequest", "GetUserListRequest", + "IngestAdEventsRequest", + "IngestAdEventsResponse", "IngestAudienceMembersRequest", "IngestAudienceMembersResponse", "IngestEventsRequest", @@ -315,13 +345,18 @@ def _get_version(dependency_name): "ListUserListsResponse", "MarketingDataInsightsServiceClient", "MatchRateRange", + "MediaQuartile", "MobileData", "MobileIdInfo", "PairData", "PairIdInfo", "PartnerAudienceInfo", + "PartnerCustomerAccount", "PartnerLink", + "PartnerLinkMetadata", "PartnerLinkServiceClient", + "Platform", + "PlatformType", "PpidData", "ProcessingErrorReason", "ProcessingWarningReason", @@ -339,6 +374,7 @@ def _get_version(dependency_name): "SearchPartnerLinksResponse", "SizeInfo", "TargetNetworkInfo", + "TargetingType", "TermsOfService", "TermsOfServiceStatus", "UpdateUserListDirectLicenseRequest", @@ -362,6 +398,8 @@ def _get_version(dependency_name): "UserListServiceClient", "UserProperties", "UserProperty", + "ViewType", + "ViewabilityInfo", "WarningCount", "WarningInfo", ) diff --git a/packages/google-ads-datamanager/google/ads/datamanager_v1/gapic_metadata.json b/packages/google-ads-datamanager/google/ads/datamanager_v1/gapic_metadata.json index e14891c3ab94..60250ca08a2d 100644 --- a/packages/google-ads-datamanager/google/ads/datamanager_v1/gapic_metadata.json +++ b/packages/google-ads-datamanager/google/ads/datamanager_v1/gapic_metadata.json @@ -10,6 +10,11 @@ "grpc": { "libraryClient": "IngestionServiceClient", "rpcs": { + "IngestAdEvents": { + "methods": [ + "ingest_ad_events" + ] + }, "IngestAudienceMembers": { "methods": [ "ingest_audience_members" @@ -35,6 +40,11 @@ "grpc-async": { "libraryClient": "IngestionServiceAsyncClient", "rpcs": { + "IngestAdEvents": { + "methods": [ + "ingest_ad_events" + ] + }, "IngestAudienceMembers": { "methods": [ "ingest_audience_members" @@ -60,6 +70,11 @@ "rest": { "libraryClient": "IngestionServiceClient", "rpcs": { + "IngestAdEvents": { + "methods": [ + "ingest_ad_events" + ] + }, "IngestAudienceMembers": { "methods": [ "ingest_audience_members" diff --git a/packages/google-ads-datamanager/google/ads/datamanager_v1/services/ingestion_service/async_client.py b/packages/google-ads-datamanager/google/ads/datamanager_v1/services/ingestion_service/async_client.py index 607803113699..8da6f7e26092 100644 --- a/packages/google-ads-datamanager/google/ads/datamanager_v1/services/ingestion_service/async_client.py +++ b/packages/google-ads-datamanager/google/ads/datamanager_v1/services/ingestion_service/async_client.py @@ -328,6 +328,7 @@ async def sample_ingest_audience_members(): # Initialize request argument(s) destinations = datamanager_v1.Destination() destinations.operating_account.account_id = "account_id_value" + destinations.operating_account.account_type = "FLOODLIGHT_CONFIG" destinations.product_destination_id = "product_destination_id_value" audience_members = datamanager_v1.AudienceMember() @@ -422,6 +423,7 @@ async def sample_remove_audience_members(): # Initialize request argument(s) destinations = datamanager_v1.Destination() destinations.operating_account.account_id = "account_id_value" + destinations.operating_account.account_type = "FLOODLIGHT_CONFIG" destinations.product_destination_id = "product_destination_id_value" audience_members = datamanager_v1.AudienceMember() @@ -513,6 +515,7 @@ async def sample_ingest_events(): # Initialize request argument(s) destinations = datamanager_v1.Destination() destinations.operating_account.account_id = "account_id_value" + destinations.operating_account.account_type = "FLOODLIGHT_CONFIG" destinations.product_destination_id = "product_destination_id_value" request = datamanager_v1.IngestEventsRequest( @@ -570,6 +573,105 @@ async def sample_ingest_events(): # Done; return the response. return response + async def ingest_ad_events( + self, + request: Optional[Union[ingestion_service.IngestAdEventsRequest, dict]] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ingestion_service.IngestAdEventsResponse: + r"""Uploads a list of [AdEvent][google.ads.datamanager.v1.AdEvent] + resources to Google Analytics. + + This feature is only available to accounts on an allowlist. + + .. 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.ads import datamanager_v1 + + async def sample_ingest_ad_events(): + # Create a client + client = datamanager_v1.IngestionServiceAsyncClient() + + # Initialize request argument(s) + ad_events = datamanager_v1.AdEvent() + ad_events.event_subtype = "EVENT_SUBTYPE_OUTBOUND_CLICK" + ad_events.ad_type = "AD_TYPE_VIDEO" + ad_events.ad_format = "AD_FORMAT_VIDEO" + ad_events.ad_placement = "AD_PLACEMENT_STORY" + ad_events.targeting_type = "TARGETING_TYPE_REMARKETING" + ad_events.platform_type = "PLATFORM_TYPE_TABLET" + ad_events.platform = "PLATFORM_WEB" + ad_events.advertiser_id = "advertiser_id_value" + ad_events.event_type = "EVENT_TYPE_CLICK" + ad_events.campaign_id = "campaign_id_value" + ad_events.campaign_name = "campaign_name_value" + ad_events.region_code = "region_code_value" + ad_events.source = "source_value" + ad_events.medium = "medium_value" + ad_events.viewability_info.view_type = "VIEW_TYPE_MRC_RENDERED" + + request = datamanager_v1.IngestAdEventsRequest( + ad_events=ad_events, + ) + + # Make the request + response = await client.ingest_ad_events(request=request) + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.ads.datamanager_v1.types.IngestAdEventsRequest, dict]]): + The request object. Request to upload ad events. + 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + google.ads.datamanager_v1.types.IngestAdEventsResponse: + Response from an ad event ingestion + operation. + + """ + # Create or coerce a protobuf request object. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, ingestion_service.IngestAdEventsRequest): + request = ingestion_service.IngestAdEventsRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.ingest_ad_events + ] + + # 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 retrieve_request_status( self, request: Optional[ diff --git a/packages/google-ads-datamanager/google/ads/datamanager_v1/services/ingestion_service/client.py b/packages/google-ads-datamanager/google/ads/datamanager_v1/services/ingestion_service/client.py index 0282585b8fe0..0dae3f323e08 100644 --- a/packages/google-ads-datamanager/google/ads/datamanager_v1/services/ingestion_service/client.py +++ b/packages/google-ads-datamanager/google/ads/datamanager_v1/services/ingestion_service/client.py @@ -743,6 +743,7 @@ def sample_ingest_audience_members(): # Initialize request argument(s) destinations = datamanager_v1.Destination() destinations.operating_account.account_id = "account_id_value" + destinations.operating_account.account_type = "FLOODLIGHT_CONFIG" destinations.product_destination_id = "product_destination_id_value" audience_members = datamanager_v1.AudienceMember() @@ -835,6 +836,7 @@ def sample_remove_audience_members(): # Initialize request argument(s) destinations = datamanager_v1.Destination() destinations.operating_account.account_id = "account_id_value" + destinations.operating_account.account_type = "FLOODLIGHT_CONFIG" destinations.product_destination_id = "product_destination_id_value" audience_members = datamanager_v1.AudienceMember() @@ -924,6 +926,7 @@ def sample_ingest_events(): # Initialize request argument(s) destinations = datamanager_v1.Destination() destinations.operating_account.account_id = "account_id_value" + destinations.operating_account.account_type = "FLOODLIGHT_CONFIG" destinations.product_destination_id = "product_destination_id_value" request = datamanager_v1.IngestEventsRequest( @@ -979,6 +982,103 @@ def sample_ingest_events(): # Done; return the response. return response + def ingest_ad_events( + self, + request: Optional[Union[ingestion_service.IngestAdEventsRequest, dict]] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ingestion_service.IngestAdEventsResponse: + r"""Uploads a list of [AdEvent][google.ads.datamanager.v1.AdEvent] + resources to Google Analytics. + + This feature is only available to accounts on an allowlist. + + .. 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.ads import datamanager_v1 + + def sample_ingest_ad_events(): + # Create a client + client = datamanager_v1.IngestionServiceClient() + + # Initialize request argument(s) + ad_events = datamanager_v1.AdEvent() + ad_events.event_subtype = "EVENT_SUBTYPE_OUTBOUND_CLICK" + ad_events.ad_type = "AD_TYPE_VIDEO" + ad_events.ad_format = "AD_FORMAT_VIDEO" + ad_events.ad_placement = "AD_PLACEMENT_STORY" + ad_events.targeting_type = "TARGETING_TYPE_REMARKETING" + ad_events.platform_type = "PLATFORM_TYPE_TABLET" + ad_events.platform = "PLATFORM_WEB" + ad_events.advertiser_id = "advertiser_id_value" + ad_events.event_type = "EVENT_TYPE_CLICK" + ad_events.campaign_id = "campaign_id_value" + ad_events.campaign_name = "campaign_name_value" + ad_events.region_code = "region_code_value" + ad_events.source = "source_value" + ad_events.medium = "medium_value" + ad_events.viewability_info.view_type = "VIEW_TYPE_MRC_RENDERED" + + request = datamanager_v1.IngestAdEventsRequest( + ad_events=ad_events, + ) + + # Make the request + response = client.ingest_ad_events(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.ads.datamanager_v1.types.IngestAdEventsRequest, dict]): + The request object. Request to upload ad events. + 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + google.ads.datamanager_v1.types.IngestAdEventsResponse: + Response from an ad event ingestion + operation. + + """ + # Create or coerce a protobuf request object. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, ingestion_service.IngestAdEventsRequest): + request = ingestion_service.IngestAdEventsRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.ingest_ad_events] + + # 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 retrieve_request_status( self, request: Optional[ diff --git a/packages/google-ads-datamanager/google/ads/datamanager_v1/services/ingestion_service/transports/base.py b/packages/google-ads-datamanager/google/ads/datamanager_v1/services/ingestion_service/transports/base.py index c65424017d17..966fbe06b59e 100644 --- a/packages/google-ads-datamanager/google/ads/datamanager_v1/services/ingestion_service/transports/base.py +++ b/packages/google-ads-datamanager/google/ads/datamanager_v1/services/ingestion_service/transports/base.py @@ -157,6 +157,11 @@ def _prep_wrapped_messages(self, client_info): default_timeout=None, client_info=client_info, ), + self.ingest_ad_events: gapic_v1.method.wrap_method( + self.ingest_ad_events, + default_timeout=None, + client_info=client_info, + ), self.retrieve_request_status: gapic_v1.method.wrap_method( self.retrieve_request_status, default_timeout=None, @@ -209,6 +214,18 @@ def ingest_events( ]: raise NotImplementedError() + @property + def ingest_ad_events( + self, + ) -> Callable[ + [ingestion_service.IngestAdEventsRequest], + Union[ + ingestion_service.IngestAdEventsResponse, + Awaitable[ingestion_service.IngestAdEventsResponse], + ], + ]: + raise NotImplementedError() + @property def retrieve_request_status( self, diff --git a/packages/google-ads-datamanager/google/ads/datamanager_v1/services/ingestion_service/transports/grpc.py b/packages/google-ads-datamanager/google/ads/datamanager_v1/services/ingestion_service/transports/grpc.py index ef983168edea..7a1ae1b62abf 100644 --- a/packages/google-ads-datamanager/google/ads/datamanager_v1/services/ingestion_service/transports/grpc.py +++ b/packages/google-ads-datamanager/google/ads/datamanager_v1/services/ingestion_service/transports/grpc.py @@ -419,6 +419,38 @@ def ingest_events( ) return self._stubs["ingest_events"] + @property + def ingest_ad_events( + self, + ) -> Callable[ + [ingestion_service.IngestAdEventsRequest], + ingestion_service.IngestAdEventsResponse, + ]: + r"""Return a callable for the ingest ad events method over gRPC. + + Uploads a list of [AdEvent][google.ads.datamanager.v1.AdEvent] + resources to Google Analytics. + + This feature is only available to accounts on an allowlist. + + Returns: + Callable[[~.IngestAdEventsRequest], + ~.IngestAdEventsResponse]: + 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 "ingest_ad_events" not in self._stubs: + self._stubs["ingest_ad_events"] = self._logged_channel.unary_unary( + "/google.ads.datamanager.v1.IngestionService/IngestAdEvents", + request_serializer=ingestion_service.IngestAdEventsRequest.serialize, + response_deserializer=ingestion_service.IngestAdEventsResponse.deserialize, + ) + return self._stubs["ingest_ad_events"] + @property def retrieve_request_status( self, diff --git a/packages/google-ads-datamanager/google/ads/datamanager_v1/services/ingestion_service/transports/grpc_asyncio.py b/packages/google-ads-datamanager/google/ads/datamanager_v1/services/ingestion_service/transports/grpc_asyncio.py index 4a6846d5dd7b..3d0d2d9c0d78 100644 --- a/packages/google-ads-datamanager/google/ads/datamanager_v1/services/ingestion_service/transports/grpc_asyncio.py +++ b/packages/google-ads-datamanager/google/ads/datamanager_v1/services/ingestion_service/transports/grpc_asyncio.py @@ -428,6 +428,38 @@ def ingest_events( ) return self._stubs["ingest_events"] + @property + def ingest_ad_events( + self, + ) -> Callable[ + [ingestion_service.IngestAdEventsRequest], + Awaitable[ingestion_service.IngestAdEventsResponse], + ]: + r"""Return a callable for the ingest ad events method over gRPC. + + Uploads a list of [AdEvent][google.ads.datamanager.v1.AdEvent] + resources to Google Analytics. + + This feature is only available to accounts on an allowlist. + + Returns: + Callable[[~.IngestAdEventsRequest], + Awaitable[~.IngestAdEventsResponse]]: + 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 "ingest_ad_events" not in self._stubs: + self._stubs["ingest_ad_events"] = self._logged_channel.unary_unary( + "/google.ads.datamanager.v1.IngestionService/IngestAdEvents", + request_serializer=ingestion_service.IngestAdEventsRequest.serialize, + response_deserializer=ingestion_service.IngestAdEventsResponse.deserialize, + ) + return self._stubs["ingest_ad_events"] + @property def retrieve_request_status( self, @@ -475,6 +507,11 @@ def _prep_wrapped_messages(self, client_info): default_timeout=None, client_info=client_info, ), + self.ingest_ad_events: self._wrap_method( + self.ingest_ad_events, + default_timeout=None, + client_info=client_info, + ), self.retrieve_request_status: self._wrap_method( self.retrieve_request_status, default_timeout=None, diff --git a/packages/google-ads-datamanager/google/ads/datamanager_v1/services/ingestion_service/transports/rest.py b/packages/google-ads-datamanager/google/ads/datamanager_v1/services/ingestion_service/transports/rest.py index 69b7f894b963..2c48d2e16e20 100644 --- a/packages/google-ads-datamanager/google/ads/datamanager_v1/services/ingestion_service/transports/rest.py +++ b/packages/google-ads-datamanager/google/ads/datamanager_v1/services/ingestion_service/transports/rest.py @@ -72,6 +72,14 @@ class IngestionServiceRestInterceptor: .. code-block:: python class MyCustomIngestionServiceInterceptor(IngestionServiceRestInterceptor): + def pre_ingest_ad_events(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_ingest_ad_events(self, response): + logging.log(f"Received response: {response}") + return response + def pre_ingest_audience_members(self, request, metadata): logging.log(f"Received request: {request}") return request, metadata @@ -110,6 +118,57 @@ def post_retrieve_request_status(self, response): """ + def pre_ingest_ad_events( + self, + request: ingestion_service.IngestAdEventsRequest, + metadata: Sequence[Tuple[str, Union[str, bytes]]], + ) -> Tuple[ + ingestion_service.IngestAdEventsRequest, Sequence[Tuple[str, Union[str, bytes]]] + ]: + """Pre-rpc interceptor for ingest_ad_events + + Override in a subclass to manipulate the request or metadata + before they are sent to the IngestionService server. + """ + return request, metadata + + def post_ingest_ad_events( + self, response: ingestion_service.IngestAdEventsResponse + ) -> ingestion_service.IngestAdEventsResponse: + """Post-rpc interceptor for ingest_ad_events + + DEPRECATED. Please use the `post_ingest_ad_events_with_metadata` + interceptor instead. + + Override in a subclass to read or manipulate the response + after it is returned by the IngestionService server but before + it is returned to user code. This `post_ingest_ad_events` interceptor runs + before the `post_ingest_ad_events_with_metadata` interceptor. + """ + return response + + def post_ingest_ad_events_with_metadata( + self, + response: ingestion_service.IngestAdEventsResponse, + metadata: Sequence[Tuple[str, Union[str, bytes]]], + ) -> Tuple[ + ingestion_service.IngestAdEventsResponse, + Sequence[Tuple[str, Union[str, bytes]]], + ]: + """Post-rpc interceptor for ingest_ad_events + + Override in a subclass to read or manipulate the response or metadata after it + is returned by the IngestionService server but before it is returned to user code. + + We recommend only using this `post_ingest_ad_events_with_metadata` + interceptor in new development instead of the `post_ingest_ad_events` interceptor. + When both interceptors are used, this `post_ingest_ad_events_with_metadata` interceptor runs after the + `post_ingest_ad_events` interceptor. The (possibly modified) response returned by + `post_ingest_ad_events` will be passed to + `post_ingest_ad_events_with_metadata`. + """ + return response, metadata + def pre_ingest_audience_members( self, request: ingestion_service.IngestAudienceMembersRequest, @@ -410,6 +469,160 @@ def __init__( self._interceptor = interceptor or IngestionServiceRestInterceptor() self._prep_wrapped_messages(client_info) + class _IngestAdEvents( + _BaseIngestionServiceRestTransport._BaseIngestAdEvents, IngestionServiceRestStub + ): + def __hash__(self): + return hash("IngestionServiceRestTransport.IngestAdEvents") + + @staticmethod + def _get_response( + host, + metadata, + query_params, + session, + timeout, + transcoded_request, + body=None, + ): + uri = transcoded_request["uri"] + method = transcoded_request["method"] + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(session, method)( + "{host}{uri}".format(host=host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + data=body, + ) + return response + + def __call__( + self, + request: ingestion_service.IngestAdEventsRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> ingestion_service.IngestAdEventsResponse: + r"""Call the ingest ad events method over HTTP. + + Args: + request (~.ingestion_service.IngestAdEventsRequest): + The request object. Request to upload ad events. + 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + ~.ingestion_service.IngestAdEventsResponse: + Response from an ad event ingestion + operation. + + """ + + http_options = _BaseIngestionServiceRestTransport._BaseIngestAdEvents._get_http_options() + + request, metadata = self._interceptor.pre_ingest_ad_events( + request, metadata + ) + transcoded_request = _BaseIngestionServiceRestTransport._BaseIngestAdEvents._get_transcoded_request( + http_options, request + ) + + body = _BaseIngestionServiceRestTransport._BaseIngestAdEvents._get_request_body_json( + transcoded_request + ) + + # Jsonify the query params + query_params = _BaseIngestionServiceRestTransport._BaseIngestAdEvents._get_query_params_json( + transcoded_request + ) + + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + logging.DEBUG + ): # pragma: NO COVER + request_url = "{host}{uri}".format( + host=self._host, uri=transcoded_request["uri"] + ) + method = transcoded_request["method"] + try: + request_payload = type(request).to_json(request) + except: + request_payload = None + http_request = { + "payload": request_payload, + "requestMethod": method, + "requestUrl": request_url, + "headers": dict(metadata), + } + _LOGGER.debug( + f"Sending request for google.ads.datamanager_v1.IngestionServiceClient.IngestAdEvents", + extra={ + "serviceName": "google.ads.datamanager.v1.IngestionService", + "rpcName": "IngestAdEvents", + "httpRequest": http_request, + "metadata": http_request["headers"], + }, + ) + + # Send the request + response = IngestionServiceRestTransport._IngestAdEvents._get_response( + self._host, + metadata, + query_params, + self._session, + timeout, + transcoded_request, + 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 = ingestion_service.IngestAdEventsResponse() + pb_resp = ingestion_service.IngestAdEventsResponse.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + + resp = self._interceptor.post_ingest_ad_events(resp) + response_metadata = [(k, str(v)) for k, v in response.headers.items()] + resp, _ = self._interceptor.post_ingest_ad_events_with_metadata( + resp, response_metadata + ) + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + logging.DEBUG + ): # pragma: NO COVER + try: + response_payload = ingestion_service.IngestAdEventsResponse.to_json( + response + ) + except: + response_payload = None + http_response = { + "payload": response_payload, + "headers": dict(response.headers), + "status": response.status_code, + } + _LOGGER.debug( + "Received response for google.ads.datamanager_v1.IngestionServiceClient.ingest_ad_events", + extra={ + "serviceName": "google.ads.datamanager.v1.IngestionService", + "rpcName": "IngestAdEvents", + "metadata": http_response["headers"], + "httpResponse": http_response, + }, + ) + return resp + class _IngestAudienceMembers( _BaseIngestionServiceRestTransport._BaseIngestAudienceMembers, IngestionServiceRestStub, @@ -1043,6 +1256,17 @@ def __call__( ) return resp + @property + def ingest_ad_events( + self, + ) -> Callable[ + [ingestion_service.IngestAdEventsRequest], + ingestion_service.IngestAdEventsResponse, + ]: + # 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._IngestAdEvents(self._session, self._host, self._interceptor) # type: ignore + @property def ingest_audience_members( self, diff --git a/packages/google-ads-datamanager/google/ads/datamanager_v1/services/ingestion_service/transports/rest_base.py b/packages/google-ads-datamanager/google/ads/datamanager_v1/services/ingestion_service/transports/rest_base.py index f0b2dc696816..b4c248b12689 100644 --- a/packages/google-ads-datamanager/google/ads/datamanager_v1/services/ingestion_service/transports/rest_base.py +++ b/packages/google-ads-datamanager/google/ads/datamanager_v1/services/ingestion_service/transports/rest_base.py @@ -87,6 +87,63 @@ def __init__( api_audience=api_audience, ) + class _BaseIngestAdEvents: + def __hash__(self): # pragma: NO COVER + return NotImplementedError("__hash__ must be implemented.") + + __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 + } + + @staticmethod + def _get_http_options(): + http_options: List[Dict[str, str]] = [ + { + "method": "post", + "uri": "/v1/adEvents:ingest", + "body": "*", + }, + ] + return http_options + + @staticmethod + def _get_transcoded_request(http_options, request): + pb_request = ingestion_service.IngestAdEventsRequest.pb(request) + transcoded_request = path_template.transcode(http_options, pb_request) + return transcoded_request + + @staticmethod + def _get_request_body_json(transcoded_request): + # Jsonify the request body + + body = json_format.MessageToJson( + transcoded_request["body"], use_integers_for_enums=True + ) + return body + + @staticmethod + def _get_query_params_json(transcoded_request): + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + use_integers_for_enums=True, + ) + ) + query_params.update( + _BaseIngestionServiceRestTransport._BaseIngestAdEvents._get_unset_required_fields( + query_params + ) + ) + + query_params["$alt"] = "json;enum-encoding=int" + return query_params + class _BaseIngestAudienceMembers: def __hash__(self): # pragma: NO COVER return NotImplementedError("__hash__ must be implemented.") diff --git a/packages/google-ads-datamanager/google/ads/datamanager_v1/services/partner_link_service/async_client.py b/packages/google-ads-datamanager/google/ads/datamanager_v1/services/partner_link_service/async_client.py index 26d9e63c41f5..33bc47086e21 100644 --- a/packages/google-ads-datamanager/google/ads/datamanager_v1/services/partner_link_service/async_client.py +++ b/packages/google-ads-datamanager/google/ads/datamanager_v1/services/partner_link_service/async_client.py @@ -343,7 +343,9 @@ async def sample_create_partner_link(): # Initialize request argument(s) partner_link = datamanager_v1.PartnerLink() partner_link.owning_account.account_id = "account_id_value" + partner_link.owning_account.account_type = "FLOODLIGHT_CONFIG" partner_link.partner_account.account_id = "account_id_value" + partner_link.partner_account.account_type = "FLOODLIGHT_CONFIG" request = datamanager_v1.CreatePartnerLinkRequest( parent="parent_value", diff --git a/packages/google-ads-datamanager/google/ads/datamanager_v1/services/partner_link_service/client.py b/packages/google-ads-datamanager/google/ads/datamanager_v1/services/partner_link_service/client.py index 71235b65c66d..ff2192e695da 100644 --- a/packages/google-ads-datamanager/google/ads/datamanager_v1/services/partner_link_service/client.py +++ b/packages/google-ads-datamanager/google/ads/datamanager_v1/services/partner_link_service/client.py @@ -774,7 +774,9 @@ def sample_create_partner_link(): # Initialize request argument(s) partner_link = datamanager_v1.PartnerLink() partner_link.owning_account.account_id = "account_id_value" + partner_link.owning_account.account_type = "FLOODLIGHT_CONFIG" partner_link.partner_account.account_id = "account_id_value" + partner_link.partner_account.account_type = "FLOODLIGHT_CONFIG" request = datamanager_v1.CreatePartnerLinkRequest( parent="parent_value", diff --git a/packages/google-ads-datamanager/google/ads/datamanager_v1/types/__init__.py b/packages/google-ads-datamanager/google/ads/datamanager_v1/types/__init__.py index 2dfc20157877..ac3a1418bd4b 100644 --- a/packages/google-ads-datamanager/google/ads/datamanager_v1/types/__init__.py +++ b/packages/google-ads-datamanager/google/ads/datamanager_v1/types/__init__.py @@ -13,6 +13,16 @@ # See the License for the specific language governing permissions and # limitations under the License. # +from .ad_event import ( + AdEvent, + AdFormat, + AdPlacement, + AdType, + AttributionHint, + Platform, + PlatformType, + TargetingType, +) from .age_range import ( AgeRange, ) @@ -47,6 +57,7 @@ ) from .encryption_info import ( AwsWrappedKeyInfo, + CoordinatorKeyInfo, EncryptionInfo, GcpWrappedKeyInfo, ) @@ -69,6 +80,8 @@ ) from .ingestion_service import ( Encoding, + IngestAdEventsRequest, + IngestAdEventsResponse, IngestAudienceMembersRequest, IngestAudienceMembersResponse, IngestEventsRequest, @@ -92,7 +105,10 @@ from .partner_link_service import ( CreatePartnerLinkRequest, DeletePartnerLinkRequest, + FeatureSet, + PartnerCustomerAccount, PartnerLink, + PartnerLinkMetadata, SearchPartnerLinksRequest, SearchPartnerLinksResponse, ) @@ -181,8 +197,21 @@ UserProperties, UserProperty, ) +from .viewability_info import ( + MediaQuartile, + ViewabilityInfo, + ViewType, +) __all__ = ( + "AdEvent", + "AdFormat", + "AdPlacement", + "AdType", + "AttributionHint", + "Platform", + "PlatformType", + "TargetingType", "AgeRange", "AudienceMember", "CompositeData", @@ -202,6 +231,7 @@ "DeviceInfo", "EncryptedUserId", "AwsWrappedKeyInfo", + "CoordinatorKeyInfo", "EncryptionInfo", "GcpWrappedKeyInfo", "ErrorReason", @@ -213,6 +243,8 @@ "EventSource", "ExperimentalField", "Gender", + "IngestAdEventsRequest", + "IngestAdEventsResponse", "IngestAudienceMembersRequest", "IngestAudienceMembersResponse", "IngestEventsRequest", @@ -229,9 +261,12 @@ "MatchRateRange", "CreatePartnerLinkRequest", "DeletePartnerLinkRequest", + "PartnerCustomerAccount", "PartnerLink", + "PartnerLinkMetadata", "SearchPartnerLinksRequest", "SearchPartnerLinksResponse", + "FeatureSet", "ErrorCount", "ErrorInfo", "WarningCount", @@ -285,4 +320,7 @@ "UserProperty", "CustomerType", "CustomerValueBucket", + "ViewabilityInfo", + "MediaQuartile", + "ViewType", ) diff --git a/packages/google-ads-datamanager/google/ads/datamanager_v1/types/ad_event.py b/packages/google-ads-datamanager/google/ads/datamanager_v1/types/ad_event.py new file mode 100644 index 000000000000..f169f6038810 --- /dev/null +++ b/packages/google-ads-datamanager/google/ads/datamanager_v1/types/ad_event.py @@ -0,0 +1,613 @@ +# -*- coding: utf-8 -*- +# Copyright 2026 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 google.protobuf.timestamp_pb2 as timestamp_pb2 # type: ignore +import proto # type: ignore + +from google.ads.datamanager_v1.types import device_info as gad_device_info +from google.ads.datamanager_v1.types import user_data as gad_user_data +from google.ads.datamanager_v1.types import viewability_info as gad_viewability_info + +__protobuf__ = proto.module( + package="google.ads.datamanager.v1", + manifest={ + "AdType", + "AdFormat", + "AdPlacement", + "TargetingType", + "PlatformType", + "Platform", + "AttributionHint", + "AdEvent", + }, +) + + +class AdType(proto.Enum): + r"""The type of the ad served. + + Values: + AD_TYPE_UNSPECIFIED (0): + Unspecified ad type. + AD_TYPE_DISPLAY (1): + Display ad. + AD_TYPE_TEXT (2): + Text ad. + AD_TYPE_IMAGE (3): + Image ad. + AD_TYPE_RICH_MEDIA (4): + Rich media ad. + AD_TYPE_HTML (5): + HTML ad. + AD_TYPE_AUDIO (6): + Audio ad. + AD_TYPE_VIDEO (7): + Video ad. + """ + + AD_TYPE_UNSPECIFIED = 0 + AD_TYPE_DISPLAY = 1 + AD_TYPE_TEXT = 2 + AD_TYPE_IMAGE = 3 + AD_TYPE_RICH_MEDIA = 4 + AD_TYPE_HTML = 5 + AD_TYPE_AUDIO = 6 + AD_TYPE_VIDEO = 7 + + +class AdFormat(proto.Enum): + r"""The format of the ad served. + + Values: + AD_FORMAT_UNSPECIFIED (0): + Unspecified ad format. + AD_FORMAT_AR (1): + AR ad. + AD_FORMAT_AUDIO (2): + Audio ad. + AD_FORMAT_BANNER (3): + Banner ad. + AD_FORMAT_BUMPER (4): + Bumper ad. + AD_FORMAT_CAROUSEL (5): + Carousel ad. + AD_FORMAT_COLLECTION (6): + Collection ad. + AD_FORMAT_IMAGE (7): + Image ad. + AD_FORMAT_INTERACTIVE (8): + Interactive ad. + AD_FORMAT_INTERSTITIAL (9): + Interstitial ad. + AD_FORMAT_IN_FEED (10): + In-feed ad. + AD_FORMAT_IN_STREAM (11): + In-stream ad. + AD_FORMAT_IN_STREAM_SKIPPABLE (12): + In-stream skippable ad. + AD_FORMAT_IN_STREAM_NON_SKIPPABLE (13): + In-stream non-skippable ad. + AD_FORMAT_NATIVE (14): + Native ad. + AD_FORMAT_SHORTS (15): + Shorts ad. + AD_FORMAT_STORY (16): + Story ad. + AD_FORMAT_SPONSORED (17): + Sponsored ad. + AD_FORMAT_VIDEO (18): + Video ad. + """ + + AD_FORMAT_UNSPECIFIED = 0 + AD_FORMAT_AR = 1 + AD_FORMAT_AUDIO = 2 + AD_FORMAT_BANNER = 3 + AD_FORMAT_BUMPER = 4 + AD_FORMAT_CAROUSEL = 5 + AD_FORMAT_COLLECTION = 6 + AD_FORMAT_IMAGE = 7 + AD_FORMAT_INTERACTIVE = 8 + AD_FORMAT_INTERSTITIAL = 9 + AD_FORMAT_IN_FEED = 10 + AD_FORMAT_IN_STREAM = 11 + AD_FORMAT_IN_STREAM_SKIPPABLE = 12 + AD_FORMAT_IN_STREAM_NON_SKIPPABLE = 13 + AD_FORMAT_NATIVE = 14 + AD_FORMAT_SHORTS = 15 + AD_FORMAT_STORY = 16 + AD_FORMAT_SPONSORED = 17 + AD_FORMAT_VIDEO = 18 + + +class AdPlacement(proto.Enum): + r"""The placement of the ad served. + + Values: + AD_PLACEMENT_UNSPECIFIED (0): + Unspecified ad placement. + AD_PLACEMENT_DISCOVER (1): + Discover placement. + AD_PLACEMENT_FEED (2): + Feed placement. + AD_PLACEMENT_FOOTER (3): + Footer placement. + AD_PLACEMENT_HEADER (4): + Header placement. + AD_PLACEMENT_HOME (5): + Home placement. + AD_PLACEMENT_IN_CONTENT (6): + In-content placement. + AD_PLACEMENT_PROMOTED (7): + Promoted placement. + AD_PLACEMENT_SEARCH (8): + Search placement. + AD_PLACEMENT_STORY (9): + Story placement. + """ + + AD_PLACEMENT_UNSPECIFIED = 0 + AD_PLACEMENT_DISCOVER = 1 + AD_PLACEMENT_FEED = 2 + AD_PLACEMENT_FOOTER = 3 + AD_PLACEMENT_HEADER = 4 + AD_PLACEMENT_HOME = 5 + AD_PLACEMENT_IN_CONTENT = 6 + AD_PLACEMENT_PROMOTED = 7 + AD_PLACEMENT_SEARCH = 8 + AD_PLACEMENT_STORY = 9 + + +class TargetingType(proto.Enum): + r"""The type of targeting used to serve the ad. + + Values: + TARGETING_TYPE_UNSPECIFIED (0): + Unspecified targeting type. + TARGETING_TYPE_AUDIENCE (1): + Audience targeting. + TARGETING_TYPE_CONTEXTUAL (2): + Contextual targeting. + TARGETING_TYPE_DEMOGRAPHIC (3): + Demographic targeting. + TARGETING_TYPE_DEVICE (4): + Device targeting. + TARGETING_TYPE_GEO (5): + Geo targeting. + TARGETING_TYPE_INTEREST (6): + Interest targeting. + TARGETING_TYPE_PURCHASE_INTENT (7): + Purchase intent targeting. + TARGETING_TYPE_REMARKETING (8): + Remarketing targeting. + """ + + TARGETING_TYPE_UNSPECIFIED = 0 + TARGETING_TYPE_AUDIENCE = 1 + TARGETING_TYPE_CONTEXTUAL = 2 + TARGETING_TYPE_DEMOGRAPHIC = 3 + TARGETING_TYPE_DEVICE = 4 + TARGETING_TYPE_GEO = 5 + TARGETING_TYPE_INTEREST = 6 + TARGETING_TYPE_PURCHASE_INTENT = 7 + TARGETING_TYPE_REMARKETING = 8 + + +class PlatformType(proto.Enum): + r"""The type of the platform on which the ad was served. + + Values: + PLATFORM_TYPE_UNSPECIFIED (0): + Unspecified platform type. + PLATFORM_TYPE_MOBILE (1): + Mobile platform. + PLATFORM_TYPE_DESKTOP (2): + Desktop platform. + PLATFORM_TYPE_CTV (3): + CTV platform. + PLATFORM_TYPE_PHONE (4): + Phone platform. + PLATFORM_TYPE_TABLET (5): + Tablet platform. + """ + + PLATFORM_TYPE_UNSPECIFIED = 0 + PLATFORM_TYPE_MOBILE = 1 + PLATFORM_TYPE_DESKTOP = 2 + PLATFORM_TYPE_CTV = 3 + PLATFORM_TYPE_PHONE = 4 + PLATFORM_TYPE_TABLET = 5 + + +class Platform(proto.Enum): + r"""Further detail of the platform on which the ad was served. + + Values: + PLATFORM_UNSPECIFIED (0): + Unspecified platform. + PLATFORM_IOS (1): + iOS platform. + PLATFORM_ANDROID (2): + Android platform. + PLATFORM_WEB (3): + Web platform. + """ + + PLATFORM_UNSPECIFIED = 0 + PLATFORM_IOS = 1 + PLATFORM_ANDROID = 2 + PLATFORM_WEB = 3 + + +class AttributionHint(proto.Enum): + r"""The partner-assumed attribution status for this ad event. + + Values: + ATTRIBUTION_HINT_UNSPECIFIED (0): + Unknown attribution status. + ATTRIBUTION_HINT_CONVERTED (1): + Converted status. + ATTRIBUTION_HINT_NOT_CONVERTED (2): + Not converted status. + """ + + ATTRIBUTION_HINT_UNSPECIFIED = 0 + ATTRIBUTION_HINT_CONVERTED = 1 + ATTRIBUTION_HINT_NOT_CONVERTED = 2 + + +class AdEvent(proto.Message): + r"""An ad event. + + 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: + advertiser_id (str): + Required. The ID of the advertiser for the ad + event. + This must match the ID sent in the linking flow. + event_type (google.ads.datamanager_v1.types.AdEvent.EventType): + Required. The type of the event. + event_subtype (google.ads.datamanager_v1.types.AdEvent.EventSubtype): + Enum value for event subtype. + + This field is a member of `oneof`_ ``event_subtype_oneof``. + event_subtype_string (str): + String value for event subtype. + + This field is a member of `oneof`_ ``event_subtype_oneof``. + timestamp (google.protobuf.timestamp_pb2.Timestamp): + Required. The time the event occurred. + event_id (str): + Optional. An ID created and managed by the + caller that uniquely identifies this event. + + Required if you want to deduplicate ad events + that are included in multiple requests. + Otherwise, this field is optional. + user_data (google.ads.datamanager_v1.types.UserData): + Optional. Multiple pieces of user-provided + data, representing the user the event is + associated with. + + It is possible to provide multiple instances of + the same type of data (e.g. email address). The + more data provided, the more likely a match will + be found. + device_info (google.ads.datamanager_v1.types.DeviceInfo): + Optional. Information gathered about the + device being used when the ad event happened. + mobile_device_id (str): + Optional. The device ID of the device that + the ad was served to. + campaign_id (str): + Required. The ID of the associated campaign. + campaign_name (str): + Required. The name of the associated + campaign. + ad_group_id (str): + Optional. The ID of the associated ad group. + ad_id (str): + Optional. The ID of the associated ad within + the group. + ad_type (google.ads.datamanager_v1.types.AdType): + Enum value for ad type. + + This field is a member of `oneof`_ ``ad_type_oneof``. + ad_type_string (str): + String value for ad type. + + This field is a member of `oneof`_ ``ad_type_oneof``. + ad_format (google.ads.datamanager_v1.types.AdFormat): + Enum value for ad format. + + This field is a member of `oneof`_ ``ad_format_oneof``. + ad_format_string (str): + String value for ad format. + + This field is a member of `oneof`_ ``ad_format_oneof``. + ad_placement (google.ads.datamanager_v1.types.AdPlacement): + Enum value for ad placement. + + This field is a member of `oneof`_ ``ad_placement_oneof``. + ad_placement_string (str): + String value for ad placement. + + This field is a member of `oneof`_ ``ad_placement_oneof``. + ad_height (int): + Optional. The height of the ad in pixels. + ad_width (int): + Optional. The width of the ad in pixels. + region_code (str): + Required. The ISO 3166-2 country plus + subdivision. + source (str): + Required. The platform source of the ad, akin + to the Google Analytics source. + medium (str): + Required. The medium of the ad, akin to the + Google Analytics medium. + targeting_type (google.ads.datamanager_v1.types.TargetingType): + Enum value for targeting type. + + This field is a member of `oneof`_ ``targeting_type_oneof``. + targeting_type_string (str): + String value for targeting type. + + This field is a member of `oneof`_ ``targeting_type_oneof``. + platform_type (google.ads.datamanager_v1.types.PlatformType): + Enum value for platform type. + + This field is a member of `oneof`_ ``platform_type_oneof``. + platform_type_string (str): + String value for platform type. + + This field is a member of `oneof`_ ``platform_type_oneof``. + platform (google.ads.datamanager_v1.types.Platform): + Enum value for platform. + + This field is a member of `oneof`_ ``platform_oneof``. + platform_string (str): + String value for platform. + + This field is a member of `oneof`_ ``platform_oneof``. + attribution_hint (google.ads.datamanager_v1.types.AttributionHint): + Optional. The partner-assumed attribution + status for this ad event. + This acts only as a signal for how the partner + assumed attribution played out, and does not + force an end result in final reports. + viewability_info (google.ads.datamanager_v1.types.ViewabilityInfo): + Required. Details of the viewability of the + ad served. + measurement_allowed (bool): + Optional. Represents if the row is allowed to + be used for measurement purposes, as governed by + applicable privacy laws within regional + jurisdiction. + + This field is a member of `oneof`_ ``_measurement_allowed``. + """ + + class EventType(proto.Enum): + r"""The type of the event. + + Values: + EVENT_TYPE_UNSPECIFIED (0): + Unspecified event type. + EVENT_TYPE_VIEW (1): + View event. + EVENT_TYPE_CLICK (2): + Click event. + """ + + EVENT_TYPE_UNSPECIFIED = 0 + EVENT_TYPE_VIEW = 1 + EVENT_TYPE_CLICK = 2 + + class EventSubtype(proto.Enum): + r"""Additional classification about the type of ad event. + + Values: + EVENT_SUBTYPE_UNSPECIFIED (0): + Unspecified event subtype. + EVENT_SUBTYPE_IMPRESSION (1): + Impression event. + EVENT_SUBTYPE_ENGAGED_VIEW (2): + Engaged view event. + EVENT_SUBTYPE_ONSITE_CLICK (3): + Onsite click event. + EVENT_SUBTYPE_OUTBOUND_CLICK (4): + Outbound click event. + """ + + EVENT_SUBTYPE_UNSPECIFIED = 0 + EVENT_SUBTYPE_IMPRESSION = 1 + EVENT_SUBTYPE_ENGAGED_VIEW = 2 + EVENT_SUBTYPE_ONSITE_CLICK = 3 + EVENT_SUBTYPE_OUTBOUND_CLICK = 4 + + advertiser_id: str = proto.Field( + proto.STRING, + number=1, + ) + event_type: EventType = proto.Field( + proto.ENUM, + number=2, + enum=EventType, + ) + event_subtype: EventSubtype = proto.Field( + proto.ENUM, + number=3, + oneof="event_subtype_oneof", + enum=EventSubtype, + ) + event_subtype_string: str = proto.Field( + proto.STRING, + number=4, + oneof="event_subtype_oneof", + ) + timestamp: timestamp_pb2.Timestamp = proto.Field( + proto.MESSAGE, + number=5, + message=timestamp_pb2.Timestamp, + ) + event_id: str = proto.Field( + proto.STRING, + number=6, + ) + user_data: gad_user_data.UserData = proto.Field( + proto.MESSAGE, + number=7, + message=gad_user_data.UserData, + ) + device_info: gad_device_info.DeviceInfo = proto.Field( + proto.MESSAGE, + number=8, + message=gad_device_info.DeviceInfo, + ) + mobile_device_id: str = proto.Field( + proto.STRING, + number=9, + ) + campaign_id: str = proto.Field( + proto.STRING, + number=10, + ) + campaign_name: str = proto.Field( + proto.STRING, + number=11, + ) + ad_group_id: str = proto.Field( + proto.STRING, + number=12, + ) + ad_id: str = proto.Field( + proto.STRING, + number=13, + ) + ad_type: "AdType" = proto.Field( + proto.ENUM, + number=14, + oneof="ad_type_oneof", + enum="AdType", + ) + ad_type_string: str = proto.Field( + proto.STRING, + number=15, + oneof="ad_type_oneof", + ) + ad_format: "AdFormat" = proto.Field( + proto.ENUM, + number=16, + oneof="ad_format_oneof", + enum="AdFormat", + ) + ad_format_string: str = proto.Field( + proto.STRING, + number=17, + oneof="ad_format_oneof", + ) + ad_placement: "AdPlacement" = proto.Field( + proto.ENUM, + number=18, + oneof="ad_placement_oneof", + enum="AdPlacement", + ) + ad_placement_string: str = proto.Field( + proto.STRING, + number=19, + oneof="ad_placement_oneof", + ) + ad_height: int = proto.Field( + proto.INT32, + number=20, + ) + ad_width: int = proto.Field( + proto.INT32, + number=21, + ) + region_code: str = proto.Field( + proto.STRING, + number=22, + ) + source: str = proto.Field( + proto.STRING, + number=23, + ) + medium: str = proto.Field( + proto.STRING, + number=24, + ) + targeting_type: "TargetingType" = proto.Field( + proto.ENUM, + number=25, + oneof="targeting_type_oneof", + enum="TargetingType", + ) + targeting_type_string: str = proto.Field( + proto.STRING, + number=26, + oneof="targeting_type_oneof", + ) + platform_type: "PlatformType" = proto.Field( + proto.ENUM, + number=27, + oneof="platform_type_oneof", + enum="PlatformType", + ) + platform_type_string: str = proto.Field( + proto.STRING, + number=28, + oneof="platform_type_oneof", + ) + platform: "Platform" = proto.Field( + proto.ENUM, + number=29, + oneof="platform_oneof", + enum="Platform", + ) + platform_string: str = proto.Field( + proto.STRING, + number=30, + oneof="platform_oneof", + ) + attribution_hint: "AttributionHint" = proto.Field( + proto.ENUM, + number=31, + enum="AttributionHint", + ) + viewability_info: gad_viewability_info.ViewabilityInfo = proto.Field( + proto.MESSAGE, + number=32, + message=gad_viewability_info.ViewabilityInfo, + ) + measurement_allowed: bool = proto.Field( + proto.BOOL, + number=33, + optional=True, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/packages/google-ads-datamanager/google/ads/datamanager_v1/types/destination.py b/packages/google-ads-datamanager/google/ads/datamanager_v1/types/destination.py index 7c9767b41b3a..a09a0b7e100c 100644 --- a/packages/google-ads-datamanager/google/ads/datamanager_v1/types/destination.py +++ b/packages/google-ads-datamanager/google/ads/datamanager_v1/types/destination.py @@ -131,7 +131,7 @@ class ProductAccount(proto.Message): Required. The ID of the account. For example, your Google Ads account ID. account_type (google.ads.datamanager_v1.types.ProductAccount.AccountType): - Optional. The type of the account. For example, + Required. The type of the account. For example, ``GOOGLE_ADS``. Either ``account_type`` or the deprecated ``product`` is required. If both are set, the values must match. diff --git a/packages/google-ads-datamanager/google/ads/datamanager_v1/types/encryption_info.py b/packages/google-ads-datamanager/google/ads/datamanager_v1/types/encryption_info.py index 83529a224cf4..3d1b83d3103c 100644 --- a/packages/google-ads-datamanager/google/ads/datamanager_v1/types/encryption_info.py +++ b/packages/google-ads-datamanager/google/ads/datamanager_v1/types/encryption_info.py @@ -25,6 +25,7 @@ "EncryptionInfo", "GcpWrappedKeyInfo", "AwsWrappedKeyInfo", + "CoordinatorKeyInfo", }, ) @@ -48,6 +49,17 @@ class EncryptionInfo(proto.Message): aws_wrapped_key_info (google.ads.datamanager_v1.types.AwsWrappedKeyInfo): Amazon Web Services wrapped key information. + This field is a member of `oneof`_ ``wrapped_key``. + coordinator_key_info (google.ads.datamanager_v1.types.CoordinatorKeyInfo): + Key information for the chosen coordinator key. + + This is not supported for the + [IngestEvents][google.ads.datamanager.v1.IngestionService.IngestEvents], + [IngestAudienceMembers][google.ads.datamanager.v1.IngestionService.IngestAudienceMembers], + and + [RemoveAudienceMembers][google.ads.datamanager.v1.IngestionService.RemoveAudienceMembers] + methods. + This field is a member of `oneof`_ ``wrapped_key``. """ @@ -63,6 +75,12 @@ class EncryptionInfo(proto.Message): oneof="wrapped_key", message="AwsWrappedKeyInfo", ) + coordinator_key_info: "CoordinatorKeyInfo" = proto.Field( + proto.MESSAGE, + number=3, + oneof="wrapped_key", + message="CoordinatorKeyInfo", + ) class GcpWrappedKeyInfo(proto.Message): @@ -176,4 +194,19 @@ class KeyType(proto.Enum): ) +class CoordinatorKeyInfo(proto.Message): + r"""Information about the coordinator key. + + Attributes: + key_id (str): + Required. The ID of the chosen coordinator + key. + """ + + key_id: str = proto.Field( + proto.STRING, + number=1, + ) + + __all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/packages/google-ads-datamanager/google/ads/datamanager_v1/types/error.py b/packages/google-ads-datamanager/google/ads/datamanager_v1/types/error.py index 3a80492b6c88..3e2c9f4ded5a 100644 --- a/packages/google-ads-datamanager/google/ads/datamanager_v1/types/error.py +++ b/packages/google-ads-datamanager/google/ads/datamanager_v1/types/error.py @@ -133,7 +133,9 @@ class ErrorReason(proto.Enum): authorization. NO_IDENTIFIERS_PROVIDED (39): Events data contains no user identifiers or - ad identifiers. + ad identifiers. For Floodlight Event ingestion + this error indicates requests contains no ad + identifiers. INVALID_PROPERTY_TYPE (40): The property type is not supported. INVALID_STREAM_TYPE (41): diff --git a/packages/google-ads-datamanager/google/ads/datamanager_v1/types/ingestion_service.py b/packages/google-ads-datamanager/google/ads/datamanager_v1/types/ingestion_service.py index a11e26292e31..6083231519fd 100644 --- a/packages/google-ads-datamanager/google/ads/datamanager_v1/types/ingestion_service.py +++ b/packages/google-ads-datamanager/google/ads/datamanager_v1/types/ingestion_service.py @@ -19,7 +19,7 @@ import proto # type: ignore -from google.ads.datamanager_v1.types import audience, destination, event +from google.ads.datamanager_v1.types import ad_event, audience, destination, event from google.ads.datamanager_v1.types import consent as gad_consent from google.ads.datamanager_v1.types import encryption_info as gad_encryption_info from google.ads.datamanager_v1.types import ( @@ -37,6 +37,8 @@ "RemoveAudienceMembersResponse", "IngestEventsRequest", "IngestEventsResponse", + "IngestAdEventsRequest", + "IngestAdEventsResponse", "RetrieveRequestStatusRequest", "RetrieveRequestStatusResponse", }, @@ -313,6 +315,41 @@ class IngestEventsResponse(proto.Message): ) +class IngestAdEventsRequest(proto.Message): + r"""Request to upload ad events. + + Attributes: + ad_events (MutableSequence[google.ads.datamanager_v1.types.AdEvent]): + Required. Required (at least 1). A list of ad + events. + encryption_info (google.ads.datamanager_v1.types.EncryptionInfo): + Optional. Information about encryption keys + which are used to encrypt the data. + validate_only (bool): + Optional. If true, the request is validated, + but not executed. + """ + + ad_events: MutableSequence[ad_event.AdEvent] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message=ad_event.AdEvent, + ) + encryption_info: gad_encryption_info.EncryptionInfo = proto.Field( + proto.MESSAGE, + number=2, + message=gad_encryption_info.EncryptionInfo, + ) + validate_only: bool = proto.Field( + proto.BOOL, + number=3, + ) + + +class IngestAdEventsResponse(proto.Message): + r"""Response from an ad event ingestion operation.""" + + class RetrieveRequestStatusRequest(proto.Message): r"""Request to get the status of request made to the DM API for a given request ID. Returns a diff --git a/packages/google-ads-datamanager/google/ads/datamanager_v1/types/partner_link_service.py b/packages/google-ads-datamanager/google/ads/datamanager_v1/types/partner_link_service.py index 727880115aa4..0f8360d9c779 100644 --- a/packages/google-ads-datamanager/google/ads/datamanager_v1/types/partner_link_service.py +++ b/packages/google-ads-datamanager/google/ads/datamanager_v1/types/partner_link_service.py @@ -24,15 +24,39 @@ __protobuf__ = proto.module( package="google.ads.datamanager.v1", manifest={ + "FeatureSet", "CreatePartnerLinkRequest", "DeletePartnerLinkRequest", "SearchPartnerLinksRequest", "SearchPartnerLinksResponse", "PartnerLink", + "PartnerCustomerAccount", + "PartnerLinkMetadata", }, ) +class FeatureSet(proto.Enum): + r"""The set of supported features for a partner link. + + Values: + FEATURE_SET_UNSPECIFIED (0): + Unspecified feature set. If unspecified, the system behavior + defaults to + [FEATURE_SET_AUDIENCE_AND_EVENT_MANAGEMENT][google.ads.datamanager.v1.FeatureSet.FEATURE_SET_AUDIENCE_AND_EVENT_MANAGEMENT]. + FEATURE_SET_AUDIENCE_AND_EVENT_MANAGEMENT (1): + Indicates a link used for audience and event + management. + FEATURE_SET_AD_EVENT_MANAGEMENT (2): + Indicates a link used for ad event + management. + """ + + FEATURE_SET_UNSPECIFIED = 0 + FEATURE_SET_AUDIENCE_AND_EVENT_MANAGEMENT = 1 + FEATURE_SET_AD_EVENT_MANAGEMENT = 2 + + class CreatePartnerLinkRequest(proto.Message): r"""Request to create a [PartnerLink][google.ads.datamanager.v1.PartnerLink] resource. @@ -193,6 +217,20 @@ class PartnerLink(proto.Message): partner_account (google.ads.datamanager_v1.types.ProductAccount): Required. The partner account granted access by the owning account. + feature_set (google.ads.datamanager_v1.types.FeatureSet): + Optional. Immutable. The set of features supported for the + partner link. If not specified, the system behavior defaults + to + [FEATURE_SET_AUDIENCE_AND_EVENT_MANAGEMENT][google.ads.datamanager.v1.FeatureSet.FEATURE_SET_AUDIENCE_AND_EVENT_MANAGEMENT]. + partner_customer_account (google.ads.datamanager_v1.types.PartnerCustomerAccount): + Optional. The customer account in the partner system. This + is required for partner links with the + [FEATURE_SET_AD_EVENT_MANAGEMENT][google.ads.datamanager.v1.FeatureSet.FEATURE_SET_AD_EVENT_MANAGEMENT] + feature set. + partner_link_metadata (google.ads.datamanager_v1.types.PartnerLinkMetadata): + Optional. Metadata associated with the partner link. This is + optional and only accepted for partner links with the + [FEATURE_SET_AD_EVENT_MANAGEMENT][google.ads.datamanager.v1.FeatureSet.FEATURE_SET_AD_EVENT_MANAGEMENT]. """ name: str = proto.Field( @@ -213,6 +251,65 @@ class PartnerLink(proto.Message): number=4, message=destination.ProductAccount, ) + feature_set: "FeatureSet" = proto.Field( + proto.ENUM, + number=5, + enum="FeatureSet", + ) + partner_customer_account: "PartnerCustomerAccount" = proto.Field( + proto.MESSAGE, + number=6, + message="PartnerCustomerAccount", + ) + partner_link_metadata: "PartnerLinkMetadata" = proto.Field( + proto.MESSAGE, + number=7, + message="PartnerLinkMetadata", + ) + + +class PartnerCustomerAccount(proto.Message): + r"""Represents a customer account in the partner's system. + + Attributes: + account_id (str): + Required. The identifier of the customer + account in the partner's ID space. + account_name (str): + Optional. The name of the account. + account_type (str): + Optional. The type of the account. Can be + used to distinguish between advertiser accounts + and business level accounts, for example. + """ + + account_id: str = proto.Field( + proto.STRING, + number=1, + ) + account_name: str = proto.Field( + proto.STRING, + number=2, + ) + account_type: str = proto.Field( + proto.STRING, + number=3, + ) + + +class PartnerLinkMetadata(proto.Message): + r"""Represents metadata associated with a partner link. + + Attributes: + implicit_accounts (MutableSequence[google.ads.datamanager_v1.types.PartnerCustomerAccount]): + Optional. The list of implicit accounts. + """ + + implicit_accounts: MutableSequence["PartnerCustomerAccount"] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="PartnerCustomerAccount", + ) __all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/packages/google-ads-datamanager/google/ads/datamanager_v1/types/viewability_info.py b/packages/google-ads-datamanager/google/ads/datamanager_v1/types/viewability_info.py new file mode 100644 index 000000000000..2c5cb59d5b7b --- /dev/null +++ b/packages/google-ads-datamanager/google/ads/datamanager_v1/types/viewability_info.py @@ -0,0 +1,145 @@ +# -*- coding: utf-8 -*- +# Copyright 2026 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 google.protobuf.duration_pb2 as duration_pb2 # type: ignore +import proto # type: ignore + +__protobuf__ = proto.module( + package="google.ads.datamanager.v1", + manifest={ + "ViewType", + "MediaQuartile", + "ViewabilityInfo", + }, +) + + +class ViewType(proto.Enum): + r"""The type of the event. + + Values: + VIEW_TYPE_UNSPECIFIED (0): + Unspecified view type. + VIEW_TYPE_MRC_VIEWED (1): + MRC viewed. + VIEW_TYPE_MRC_RENDERED (2): + MRC rendered. + """ + + VIEW_TYPE_UNSPECIFIED = 0 + VIEW_TYPE_MRC_VIEWED = 1 + VIEW_TYPE_MRC_RENDERED = 2 + + +class MediaQuartile(proto.Enum): + r"""The amount of the media that was played as discrete + quartiles. + + Values: + MEDIA_QUARTILE_UNSPECIFIED (0): + Unspecified media quartile. + MEDIA_QUARTILE_START (1): + Start. + MEDIA_QUARTILE_FIRST_QUARTILE (2): + First quartile. + MEDIA_QUARTILE_MIDPOINT (3): + Midpoint. + MEDIA_QUARTILE_THIRD_QUARTILE (4): + Third quartile. + MEDIA_QUARTILE_COMPLETE (5): + Complete. + """ + + MEDIA_QUARTILE_UNSPECIFIED = 0 + MEDIA_QUARTILE_START = 1 + MEDIA_QUARTILE_FIRST_QUARTILE = 2 + MEDIA_QUARTILE_MIDPOINT = 3 + MEDIA_QUARTILE_THIRD_QUARTILE = 4 + MEDIA_QUARTILE_COMPLETE = 5 + + +class ViewabilityInfo(proto.Message): + r"""Details of the viewability of the ad served. + + Attributes: + view_type (google.ads.datamanager_v1.types.ViewType): + Required. The type of the event. + viewable_percent (int): + Optional. The numerical percent (0-100) of + the pixels that were viewable. + viewable_duration (google.protobuf.duration_pb2.Duration): + Optional. The amount of time the ad was + viewable for. + media_skippable (bool): + Optional. Whether the ad media was skippable + or not. + media_quartile (google.ads.datamanager_v1.types.MediaQuartile): + Optional. The amount of the media that was + played as discrete quartiles. + media_duration (google.protobuf.duration_pb2.Duration): + Optional. The duration of the ad media. + media_volume_percent (int): + Optional. The numerical percent (0-100) of + the volume of the media playback. + playback_duration (google.protobuf.duration_pb2.Duration): + Optional. The duration of playback of the ad + media, regardless of whether it was viewable or + not. + """ + + view_type: "ViewType" = proto.Field( + proto.ENUM, + number=1, + enum="ViewType", + ) + viewable_percent: int = proto.Field( + proto.INT32, + number=2, + ) + viewable_duration: duration_pb2.Duration = proto.Field( + proto.MESSAGE, + number=3, + message=duration_pb2.Duration, + ) + media_skippable: bool = proto.Field( + proto.BOOL, + number=4, + ) + media_quartile: "MediaQuartile" = proto.Field( + proto.ENUM, + number=5, + enum="MediaQuartile", + ) + media_duration: duration_pb2.Duration = proto.Field( + proto.MESSAGE, + number=6, + message=duration_pb2.Duration, + ) + media_volume_percent: int = proto.Field( + proto.INT32, + number=7, + ) + playback_duration: duration_pb2.Duration = proto.Field( + proto.MESSAGE, + number=8, + message=duration_pb2.Duration, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/packages/google-ads-datamanager/samples/generated_samples/datamanager_v1_generated_ingestion_service_ingest_ad_events_async.py b/packages/google-ads-datamanager/samples/generated_samples/datamanager_v1_generated_ingestion_service_ingest_ad_events_async.py new file mode 100644 index 000000000000..46c9a73da5c6 --- /dev/null +++ b/packages/google-ads-datamanager/samples/generated_samples/datamanager_v1_generated_ingestion_service_ingest_ad_events_async.py @@ -0,0 +1,70 @@ +# -*- coding: utf-8 -*- +# Copyright 2026 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 IngestAdEvents +# 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-ads-datamanager + + +# [START datamanager_v1_generated_IngestionService_IngestAdEvents_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.ads import datamanager_v1 + + +async def sample_ingest_ad_events(): + # Create a client + client = datamanager_v1.IngestionServiceAsyncClient() + + # Initialize request argument(s) + ad_events = datamanager_v1.AdEvent() + ad_events.event_subtype = "EVENT_SUBTYPE_OUTBOUND_CLICK" + ad_events.ad_type = "AD_TYPE_VIDEO" + ad_events.ad_format = "AD_FORMAT_VIDEO" + ad_events.ad_placement = "AD_PLACEMENT_STORY" + ad_events.targeting_type = "TARGETING_TYPE_REMARKETING" + ad_events.platform_type = "PLATFORM_TYPE_TABLET" + ad_events.platform = "PLATFORM_WEB" + ad_events.advertiser_id = "advertiser_id_value" + ad_events.event_type = "EVENT_TYPE_CLICK" + ad_events.campaign_id = "campaign_id_value" + ad_events.campaign_name = "campaign_name_value" + ad_events.region_code = "region_code_value" + ad_events.source = "source_value" + ad_events.medium = "medium_value" + ad_events.viewability_info.view_type = "VIEW_TYPE_MRC_RENDERED" + + request = datamanager_v1.IngestAdEventsRequest( + ad_events=ad_events, + ) + + # Make the request + response = await client.ingest_ad_events(request=request) + + # Handle the response + print(response) + + +# [END datamanager_v1_generated_IngestionService_IngestAdEvents_async] diff --git a/packages/google-ads-datamanager/samples/generated_samples/datamanager_v1_generated_ingestion_service_ingest_ad_events_sync.py b/packages/google-ads-datamanager/samples/generated_samples/datamanager_v1_generated_ingestion_service_ingest_ad_events_sync.py new file mode 100644 index 000000000000..4ed2a906cec8 --- /dev/null +++ b/packages/google-ads-datamanager/samples/generated_samples/datamanager_v1_generated_ingestion_service_ingest_ad_events_sync.py @@ -0,0 +1,70 @@ +# -*- coding: utf-8 -*- +# Copyright 2026 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 IngestAdEvents +# 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-ads-datamanager + + +# [START datamanager_v1_generated_IngestionService_IngestAdEvents_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.ads import datamanager_v1 + + +def sample_ingest_ad_events(): + # Create a client + client = datamanager_v1.IngestionServiceClient() + + # Initialize request argument(s) + ad_events = datamanager_v1.AdEvent() + ad_events.event_subtype = "EVENT_SUBTYPE_OUTBOUND_CLICK" + ad_events.ad_type = "AD_TYPE_VIDEO" + ad_events.ad_format = "AD_FORMAT_VIDEO" + ad_events.ad_placement = "AD_PLACEMENT_STORY" + ad_events.targeting_type = "TARGETING_TYPE_REMARKETING" + ad_events.platform_type = "PLATFORM_TYPE_TABLET" + ad_events.platform = "PLATFORM_WEB" + ad_events.advertiser_id = "advertiser_id_value" + ad_events.event_type = "EVENT_TYPE_CLICK" + ad_events.campaign_id = "campaign_id_value" + ad_events.campaign_name = "campaign_name_value" + ad_events.region_code = "region_code_value" + ad_events.source = "source_value" + ad_events.medium = "medium_value" + ad_events.viewability_info.view_type = "VIEW_TYPE_MRC_RENDERED" + + request = datamanager_v1.IngestAdEventsRequest( + ad_events=ad_events, + ) + + # Make the request + response = client.ingest_ad_events(request=request) + + # Handle the response + print(response) + + +# [END datamanager_v1_generated_IngestionService_IngestAdEvents_sync] diff --git a/packages/google-ads-datamanager/samples/generated_samples/datamanager_v1_generated_ingestion_service_ingest_audience_members_async.py b/packages/google-ads-datamanager/samples/generated_samples/datamanager_v1_generated_ingestion_service_ingest_audience_members_async.py index d3d68a8377ca..d3ca2dce6215 100644 --- a/packages/google-ads-datamanager/samples/generated_samples/datamanager_v1_generated_ingestion_service_ingest_audience_members_async.py +++ b/packages/google-ads-datamanager/samples/generated_samples/datamanager_v1_generated_ingestion_service_ingest_audience_members_async.py @@ -41,6 +41,7 @@ async def sample_ingest_audience_members(): # Initialize request argument(s) destinations = datamanager_v1.Destination() destinations.operating_account.account_id = "account_id_value" + destinations.operating_account.account_type = "FLOODLIGHT_CONFIG" destinations.product_destination_id = "product_destination_id_value" audience_members = datamanager_v1.AudienceMember() diff --git a/packages/google-ads-datamanager/samples/generated_samples/datamanager_v1_generated_ingestion_service_ingest_audience_members_sync.py b/packages/google-ads-datamanager/samples/generated_samples/datamanager_v1_generated_ingestion_service_ingest_audience_members_sync.py index 7de1d5b46040..2250290d10b4 100644 --- a/packages/google-ads-datamanager/samples/generated_samples/datamanager_v1_generated_ingestion_service_ingest_audience_members_sync.py +++ b/packages/google-ads-datamanager/samples/generated_samples/datamanager_v1_generated_ingestion_service_ingest_audience_members_sync.py @@ -41,6 +41,7 @@ def sample_ingest_audience_members(): # Initialize request argument(s) destinations = datamanager_v1.Destination() destinations.operating_account.account_id = "account_id_value" + destinations.operating_account.account_type = "FLOODLIGHT_CONFIG" destinations.product_destination_id = "product_destination_id_value" audience_members = datamanager_v1.AudienceMember() diff --git a/packages/google-ads-datamanager/samples/generated_samples/datamanager_v1_generated_ingestion_service_ingest_events_async.py b/packages/google-ads-datamanager/samples/generated_samples/datamanager_v1_generated_ingestion_service_ingest_events_async.py index 207690c0aeac..f85295c2ba13 100644 --- a/packages/google-ads-datamanager/samples/generated_samples/datamanager_v1_generated_ingestion_service_ingest_events_async.py +++ b/packages/google-ads-datamanager/samples/generated_samples/datamanager_v1_generated_ingestion_service_ingest_events_async.py @@ -41,6 +41,7 @@ async def sample_ingest_events(): # Initialize request argument(s) destinations = datamanager_v1.Destination() destinations.operating_account.account_id = "account_id_value" + destinations.operating_account.account_type = "FLOODLIGHT_CONFIG" destinations.product_destination_id = "product_destination_id_value" request = datamanager_v1.IngestEventsRequest( diff --git a/packages/google-ads-datamanager/samples/generated_samples/datamanager_v1_generated_ingestion_service_ingest_events_sync.py b/packages/google-ads-datamanager/samples/generated_samples/datamanager_v1_generated_ingestion_service_ingest_events_sync.py index fe1ce62c6d29..855ecf9cff19 100644 --- a/packages/google-ads-datamanager/samples/generated_samples/datamanager_v1_generated_ingestion_service_ingest_events_sync.py +++ b/packages/google-ads-datamanager/samples/generated_samples/datamanager_v1_generated_ingestion_service_ingest_events_sync.py @@ -41,6 +41,7 @@ def sample_ingest_events(): # Initialize request argument(s) destinations = datamanager_v1.Destination() destinations.operating_account.account_id = "account_id_value" + destinations.operating_account.account_type = "FLOODLIGHT_CONFIG" destinations.product_destination_id = "product_destination_id_value" request = datamanager_v1.IngestEventsRequest( diff --git a/packages/google-ads-datamanager/samples/generated_samples/datamanager_v1_generated_ingestion_service_remove_audience_members_async.py b/packages/google-ads-datamanager/samples/generated_samples/datamanager_v1_generated_ingestion_service_remove_audience_members_async.py index fcb903557616..1fb0bf52b857 100644 --- a/packages/google-ads-datamanager/samples/generated_samples/datamanager_v1_generated_ingestion_service_remove_audience_members_async.py +++ b/packages/google-ads-datamanager/samples/generated_samples/datamanager_v1_generated_ingestion_service_remove_audience_members_async.py @@ -41,6 +41,7 @@ async def sample_remove_audience_members(): # Initialize request argument(s) destinations = datamanager_v1.Destination() destinations.operating_account.account_id = "account_id_value" + destinations.operating_account.account_type = "FLOODLIGHT_CONFIG" destinations.product_destination_id = "product_destination_id_value" audience_members = datamanager_v1.AudienceMember() diff --git a/packages/google-ads-datamanager/samples/generated_samples/datamanager_v1_generated_ingestion_service_remove_audience_members_sync.py b/packages/google-ads-datamanager/samples/generated_samples/datamanager_v1_generated_ingestion_service_remove_audience_members_sync.py index 0256f6628c54..b90028e39d52 100644 --- a/packages/google-ads-datamanager/samples/generated_samples/datamanager_v1_generated_ingestion_service_remove_audience_members_sync.py +++ b/packages/google-ads-datamanager/samples/generated_samples/datamanager_v1_generated_ingestion_service_remove_audience_members_sync.py @@ -41,6 +41,7 @@ def sample_remove_audience_members(): # Initialize request argument(s) destinations = datamanager_v1.Destination() destinations.operating_account.account_id = "account_id_value" + destinations.operating_account.account_type = "FLOODLIGHT_CONFIG" destinations.product_destination_id = "product_destination_id_value" audience_members = datamanager_v1.AudienceMember() diff --git a/packages/google-ads-datamanager/samples/generated_samples/datamanager_v1_generated_partner_link_service_create_partner_link_async.py b/packages/google-ads-datamanager/samples/generated_samples/datamanager_v1_generated_partner_link_service_create_partner_link_async.py index 340fd349b76e..f1f85560d7ef 100644 --- a/packages/google-ads-datamanager/samples/generated_samples/datamanager_v1_generated_partner_link_service_create_partner_link_async.py +++ b/packages/google-ads-datamanager/samples/generated_samples/datamanager_v1_generated_partner_link_service_create_partner_link_async.py @@ -41,7 +41,9 @@ async def sample_create_partner_link(): # Initialize request argument(s) partner_link = datamanager_v1.PartnerLink() partner_link.owning_account.account_id = "account_id_value" + partner_link.owning_account.account_type = "FLOODLIGHT_CONFIG" partner_link.partner_account.account_id = "account_id_value" + partner_link.partner_account.account_type = "FLOODLIGHT_CONFIG" request = datamanager_v1.CreatePartnerLinkRequest( parent="parent_value", diff --git a/packages/google-ads-datamanager/samples/generated_samples/datamanager_v1_generated_partner_link_service_create_partner_link_sync.py b/packages/google-ads-datamanager/samples/generated_samples/datamanager_v1_generated_partner_link_service_create_partner_link_sync.py index 4e48718c3aa9..623f21b963cf 100644 --- a/packages/google-ads-datamanager/samples/generated_samples/datamanager_v1_generated_partner_link_service_create_partner_link_sync.py +++ b/packages/google-ads-datamanager/samples/generated_samples/datamanager_v1_generated_partner_link_service_create_partner_link_sync.py @@ -41,7 +41,9 @@ def sample_create_partner_link(): # Initialize request argument(s) partner_link = datamanager_v1.PartnerLink() partner_link.owning_account.account_id = "account_id_value" + partner_link.owning_account.account_type = "FLOODLIGHT_CONFIG" partner_link.partner_account.account_id = "account_id_value" + partner_link.partner_account.account_type = "FLOODLIGHT_CONFIG" request = datamanager_v1.CreatePartnerLinkRequest( parent="parent_value", diff --git a/packages/google-ads-datamanager/samples/generated_samples/snippet_metadata_google.ads.datamanager.v1.json b/packages/google-ads-datamanager/samples/generated_samples/snippet_metadata_google.ads.datamanager.v1.json index edbf7d3b3841..747067e4d585 100644 --- a/packages/google-ads-datamanager/samples/generated_samples/snippet_metadata_google.ads.datamanager.v1.json +++ b/packages/google-ads-datamanager/samples/generated_samples/snippet_metadata_google.ads.datamanager.v1.json @@ -11,6 +11,159 @@ "version": "0.9.0" }, "snippets": [ + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.ads.datamanager_v1.IngestionServiceAsyncClient", + "shortName": "IngestionServiceAsyncClient" + }, + "fullName": "google.ads.datamanager_v1.IngestionServiceAsyncClient.ingest_ad_events", + "method": { + "fullName": "google.ads.datamanager.v1.IngestionService.IngestAdEvents", + "service": { + "fullName": "google.ads.datamanager.v1.IngestionService", + "shortName": "IngestionService" + }, + "shortName": "IngestAdEvents" + }, + "parameters": [ + { + "name": "request", + "type": "google.ads.datamanager_v1.types.IngestAdEventsRequest" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, Union[str, bytes]]]" + } + ], + "resultType": "google.ads.datamanager_v1.types.IngestAdEventsResponse", + "shortName": "ingest_ad_events" + }, + "description": "Sample for IngestAdEvents", + "file": "datamanager_v1_generated_ingestion_service_ingest_ad_events_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "datamanager_v1_generated_IngestionService_IngestAdEvents_async", + "segments": [ + { + "end": 68, + "start": 27, + "type": "FULL" + }, + { + "end": 68, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 62, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 65, + "start": 63, + "type": "REQUEST_EXECUTION" + }, + { + "end": 69, + "start": 66, + "type": "RESPONSE_HANDLING" + } + ], + "title": "datamanager_v1_generated_ingestion_service_ingest_ad_events_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.ads.datamanager_v1.IngestionServiceClient", + "shortName": "IngestionServiceClient" + }, + "fullName": "google.ads.datamanager_v1.IngestionServiceClient.ingest_ad_events", + "method": { + "fullName": "google.ads.datamanager.v1.IngestionService.IngestAdEvents", + "service": { + "fullName": "google.ads.datamanager.v1.IngestionService", + "shortName": "IngestionService" + }, + "shortName": "IngestAdEvents" + }, + "parameters": [ + { + "name": "request", + "type": "google.ads.datamanager_v1.types.IngestAdEventsRequest" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, Union[str, bytes]]]" + } + ], + "resultType": "google.ads.datamanager_v1.types.IngestAdEventsResponse", + "shortName": "ingest_ad_events" + }, + "description": "Sample for IngestAdEvents", + "file": "datamanager_v1_generated_ingestion_service_ingest_ad_events_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "datamanager_v1_generated_IngestionService_IngestAdEvents_sync", + "segments": [ + { + "end": 68, + "start": 27, + "type": "FULL" + }, + { + "end": 68, + "start": 27, + "type": "SHORT" + }, + { + "end": 40, + "start": 38, + "type": "CLIENT_INITIALIZATION" + }, + { + "end": 62, + "start": 41, + "type": "REQUEST_INITIALIZATION" + }, + { + "end": 65, + "start": 63, + "type": "REQUEST_EXECUTION" + }, + { + "end": 69, + "start": 66, + "type": "RESPONSE_HANDLING" + } + ], + "title": "datamanager_v1_generated_ingestion_service_ingest_ad_events_sync.py" + }, { "canonical": true, "clientMethod": { @@ -56,12 +209,12 @@ "regionTag": "datamanager_v1_generated_IngestionService_IngestAudienceMembers_async", "segments": [ { - "end": 59, + "end": 60, "start": 27, "type": "FULL" }, { - "end": 59, + "end": 60, "start": 27, "type": "SHORT" }, @@ -71,18 +224,18 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 53, + "end": 54, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 56, - "start": 54, + "end": 57, + "start": 55, "type": "REQUEST_EXECUTION" }, { - "end": 60, - "start": 57, + "end": 61, + "start": 58, "type": "RESPONSE_HANDLING" } ], @@ -132,12 +285,12 @@ "regionTag": "datamanager_v1_generated_IngestionService_IngestAudienceMembers_sync", "segments": [ { - "end": 59, + "end": 60, "start": 27, "type": "FULL" }, { - "end": 59, + "end": 60, "start": 27, "type": "SHORT" }, @@ -147,18 +300,18 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 53, + "end": 54, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 56, - "start": 54, + "end": 57, + "start": 55, "type": "REQUEST_EXECUTION" }, { - "end": 60, - "start": 57, + "end": 61, + "start": 58, "type": "RESPONSE_HANDLING" } ], @@ -209,12 +362,12 @@ "regionTag": "datamanager_v1_generated_IngestionService_IngestEvents_async", "segments": [ { - "end": 55, + "end": 56, "start": 27, "type": "FULL" }, { - "end": 55, + "end": 56, "start": 27, "type": "SHORT" }, @@ -224,18 +377,18 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 49, + "end": 50, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 52, - "start": 50, + "end": 53, + "start": 51, "type": "REQUEST_EXECUTION" }, { - "end": 56, - "start": 53, + "end": 57, + "start": 54, "type": "RESPONSE_HANDLING" } ], @@ -285,12 +438,12 @@ "regionTag": "datamanager_v1_generated_IngestionService_IngestEvents_sync", "segments": [ { - "end": 55, + "end": 56, "start": 27, "type": "FULL" }, { - "end": 55, + "end": 56, "start": 27, "type": "SHORT" }, @@ -300,18 +453,18 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 49, + "end": 50, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 52, - "start": 50, + "end": 53, + "start": 51, "type": "REQUEST_EXECUTION" }, { - "end": 56, - "start": 53, + "end": 57, + "start": 54, "type": "RESPONSE_HANDLING" } ], @@ -362,12 +515,12 @@ "regionTag": "datamanager_v1_generated_IngestionService_RemoveAudienceMembers_async", "segments": [ { - "end": 59, + "end": 60, "start": 27, "type": "FULL" }, { - "end": 59, + "end": 60, "start": 27, "type": "SHORT" }, @@ -377,18 +530,18 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 53, + "end": 54, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 56, - "start": 54, + "end": 57, + "start": 55, "type": "REQUEST_EXECUTION" }, { - "end": 60, - "start": 57, + "end": 61, + "start": 58, "type": "RESPONSE_HANDLING" } ], @@ -438,12 +591,12 @@ "regionTag": "datamanager_v1_generated_IngestionService_RemoveAudienceMembers_sync", "segments": [ { - "end": 59, + "end": 60, "start": 27, "type": "FULL" }, { - "end": 59, + "end": 60, "start": 27, "type": "SHORT" }, @@ -453,18 +606,18 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 53, + "end": 54, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 56, - "start": 54, + "end": 57, + "start": 55, "type": "REQUEST_EXECUTION" }, { - "end": 60, - "start": 57, + "end": 61, + "start": 58, "type": "RESPONSE_HANDLING" } ], @@ -829,12 +982,12 @@ "regionTag": "datamanager_v1_generated_PartnerLinkService_CreatePartnerLink_async", "segments": [ { - "end": 56, + "end": 58, "start": 27, "type": "FULL" }, { - "end": 56, + "end": 58, "start": 27, "type": "SHORT" }, @@ -844,18 +997,18 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 50, + "end": 52, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 53, - "start": 51, + "end": 55, + "start": 53, "type": "REQUEST_EXECUTION" }, { - "end": 57, - "start": 54, + "end": 59, + "start": 56, "type": "RESPONSE_HANDLING" } ], @@ -913,12 +1066,12 @@ "regionTag": "datamanager_v1_generated_PartnerLinkService_CreatePartnerLink_sync", "segments": [ { - "end": 56, + "end": 58, "start": 27, "type": "FULL" }, { - "end": 56, + "end": 58, "start": 27, "type": "SHORT" }, @@ -928,18 +1081,18 @@ "type": "CLIENT_INITIALIZATION" }, { - "end": 50, + "end": 52, "start": 41, "type": "REQUEST_INITIALIZATION" }, { - "end": 53, - "start": 51, + "end": 55, + "start": 53, "type": "REQUEST_EXECUTION" }, { - "end": 57, - "start": 54, + "end": 59, + "start": 56, "type": "RESPONSE_HANDLING" } ], diff --git a/packages/google-ads-datamanager/tests/unit/gapic/datamanager_v1/test_ingestion_service.py b/packages/google-ads-datamanager/tests/unit/gapic/datamanager_v1/test_ingestion_service.py index dcd7752d8bd6..4c240410032b 100644 --- a/packages/google-ads-datamanager/tests/unit/gapic/datamanager_v1/test_ingestion_service.py +++ b/packages/google-ads-datamanager/tests/unit/gapic/datamanager_v1/test_ingestion_service.py @@ -39,6 +39,7 @@ HAS_GOOGLE_AUTH_AIO = False import google.auth +import google.protobuf.duration_pb2 as duration_pb2 # type: ignore import google.protobuf.timestamp_pb2 as timestamp_pb2 # type: ignore from google.api_core import ( client_options, @@ -59,6 +60,7 @@ transports, ) from google.ads.datamanager_v1.types import ( + ad_event, audience, cart_data, consent, @@ -74,6 +76,7 @@ terms_of_service, user_data, user_properties, + viewability_info, ) CRED_INFO_JSON = { @@ -1926,6 +1929,179 @@ async def test_ingest_events_async(request_type, transport: str = "grpc_asyncio" assert response.request_id == "request_id_value" +@pytest.mark.parametrize( + "request_type", + [ + ingestion_service.IngestAdEventsRequest(), + {}, + ], +) +def test_ingest_ad_events(request_type, transport: str = "grpc"): + client = IngestionServiceClient( + 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.ingest_ad_events), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = ingestion_service.IngestAdEventsResponse() + response = client.ingest_ad_events(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = ingestion_service.IngestAdEventsRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, ingestion_service.IngestAdEventsResponse) + + +def test_ingest_ad_events_non_empty_request_with_auto_populated_field(): + # This test is a coverage failsafe to make sure that UUID4 fields are + # automatically populated, according to AIP-4235, with non-empty requests. + client = IngestionServiceClient( + 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 = ingestion_service.IngestAdEventsRequest() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.ingest_ad_events), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.ingest_ad_events(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + request_msg = ingestion_service.IngestAdEventsRequest() + assert args[0] == request_msg + + +def test_ingest_ad_events_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = IngestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.ingest_ad_events in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.ingest_ad_events] = ( + mock_rpc + ) + request = {} + client.ingest_ad_events(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.ingest_ad_events(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_ingest_ad_events_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = IngestionServiceAsyncClient( + credentials=async_anonymous_credentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.ingest_ad_events + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.AsyncMock() + mock_rpc.return_value = mock.Mock() + client._client._transport._wrapped_methods[ + client._client._transport.ingest_ad_events + ] = mock_rpc + + request = {} + await client.ingest_ad_events(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + await client.ingest_ad_events(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +@pytest.mark.parametrize( + "request_type", + [ + ingestion_service.IngestAdEventsRequest(), + {}, + ], +) +async def test_ingest_ad_events_async(request_type, transport: str = "grpc_asyncio"): + client = IngestionServiceAsyncClient( + credentials=async_anonymous_credentials(), + 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.ingest_ad_events), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + ingestion_service.IngestAdEventsResponse() + ) + response = await client.ingest_ad_events(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = ingestion_service.IngestAdEventsRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, ingestion_service.IngestAdEventsResponse) + + @pytest.mark.parametrize( "request_type", [ @@ -2500,6 +2676,124 @@ def test_ingest_events_rest_unset_required_fields(): ) +def test_ingest_ad_events_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = IngestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.ingest_ad_events in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.ingest_ad_events] = ( + mock_rpc + ) + + request = {} + client.ingest_ad_events(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.ingest_ad_events(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_ingest_ad_events_rest_required_fields( + request_type=ingestion_service.IngestAdEventsRequest, +): + transport_class = transports.IngestionServiceRestTransport + + 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() + ).ingest_ad_events._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() + ).ingest_ad_events._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + + client = IngestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = ingestion_service.IngestAdEventsResponse() + # 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 = ingestion_service.IngestAdEventsResponse.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 + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + + response = client.ingest_ad_events(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert sorted(expected_params) == sorted(actual_params) + + +def test_ingest_ad_events_rest_unset_required_fields(): + transport = transports.IngestionServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.ingest_ad_events._get_unset_required_fields({}) + assert set(unset_fields) == (set(()) & set(("adEvents",))) + + def test_retrieve_request_status_rest_use_cached_wrapped_rpc(): # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, # instead of constructing them on each call @@ -2808,6 +3102,26 @@ def test_ingest_events_empty_call_grpc(): assert args[0] == request_msg +# This test is a coverage failsafe to make sure that totally empty calls, +# i.e. request == None and no flattened fields passed, work. +def test_ingest_ad_events_empty_call_grpc(): + client = IngestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Mock the actual call, and fake the request. + with mock.patch.object(type(client.transport.ingest_ad_events), "__call__") as call: + call.return_value = ingestion_service.IngestAdEventsResponse() + client.ingest_ad_events(request=None) + + # Establish that the underlying stub method was called. + call.assert_called() + _, args, _ = call.mock_calls[0] + request_msg = ingestion_service.IngestAdEventsRequest() + assert args[0] == request_msg + + # This test is a coverage failsafe to make sure that totally empty calls, # i.e. request == None and no flattened fields passed, work. def test_retrieve_request_status_empty_call_grpc(): @@ -2926,6 +3240,30 @@ async def test_ingest_events_empty_call_grpc_asyncio(): assert args[0] == request_msg +# This test is a coverage failsafe to make sure that totally empty calls, +# i.e. request == None and no flattened fields passed, work. +@pytest.mark.asyncio +async def test_ingest_ad_events_empty_call_grpc_asyncio(): + client = IngestionServiceAsyncClient( + credentials=async_anonymous_credentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call, and fake the request. + with mock.patch.object(type(client.transport.ingest_ad_events), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + ingestion_service.IngestAdEventsResponse() + ) + await client.ingest_ad_events(request=None) + + # Establish that the underlying stub method was called. + call.assert_called() + _, args, _ = call.mock_calls[0] + request_msg = ingestion_service.IngestAdEventsRequest() + assert args[0] == request_msg + + # This test is a coverage failsafe to make sure that totally empty calls, # i.e. request == None and no flattened fields passed, work. @pytest.mark.asyncio @@ -3367,6 +3705,139 @@ def test_ingest_events_rest_interceptors(null_interceptor): post_with_metadata.assert_called_once() +def test_ingest_ad_events_rest_bad_request( + request_type=ingestion_service.IngestAdEventsRequest, +): + client = IngestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + # send a request that will satisfy transcoding + request_init = {} + 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 = mock.Mock() + json_return_value = "" + response_value.json = mock.Mock(return_value={}) + response_value.status_code = 400 + response_value.request = mock.Mock() + req.return_value = response_value + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + client.ingest_ad_events(request) + + +@pytest.mark.parametrize( + "request_type", + [ + ingestion_service.IngestAdEventsRequest, + dict, + ], +) +def test_ingest_ad_events_rest_call_success(request_type): + client = IngestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + # send a request that will satisfy transcoding + request_init = {} + 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 = ingestion_service.IngestAdEventsResponse() + + # Wrap the value into a proper Response obj + response_value = mock.Mock() + response_value.status_code = 200 + + # Convert return value to protobuf type + return_value = ingestion_service.IngestAdEventsResponse.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 + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + response = client.ingest_ad_events(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, ingestion_service.IngestAdEventsResponse) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_ingest_ad_events_rest_interceptors(null_interceptor): + transport = transports.IngestionServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.IngestionServiceRestInterceptor(), + ) + client = IngestionServiceClient(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.IngestionServiceRestInterceptor, "post_ingest_ad_events" + ) as post, + mock.patch.object( + transports.IngestionServiceRestInterceptor, + "post_ingest_ad_events_with_metadata", + ) as post_with_metadata, + mock.patch.object( + transports.IngestionServiceRestInterceptor, "pre_ingest_ad_events" + ) as pre, + ): + pre.assert_not_called() + post.assert_not_called() + post_with_metadata.assert_not_called() + pb_message = ingestion_service.IngestAdEventsRequest.pb( + ingestion_service.IngestAdEventsRequest() + ) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = mock.Mock() + req.return_value.status_code = 200 + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + return_value = ingestion_service.IngestAdEventsResponse.to_json( + ingestion_service.IngestAdEventsResponse() + ) + req.return_value.content = return_value + + request = ingestion_service.IngestAdEventsRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = ingestion_service.IngestAdEventsResponse() + post_with_metadata.return_value = ( + ingestion_service.IngestAdEventsResponse(), + metadata, + ) + + client.ingest_ad_events( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + post_with_metadata.assert_called_once() + + def test_retrieve_request_status_rest_bad_request( request_type=ingestion_service.RetrieveRequestStatusRequest, ): @@ -3568,6 +4039,25 @@ def test_ingest_events_empty_call_rest(): assert args[0] == request_msg +# This test is a coverage failsafe to make sure that totally empty calls, +# i.e. request == None and no flattened fields passed, work. +def test_ingest_ad_events_empty_call_rest(): + client = IngestionServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the actual call, and fake the request. + with mock.patch.object(type(client.transport.ingest_ad_events), "__call__") as call: + client.ingest_ad_events(request=None) + + # Establish that the underlying stub method was called. + call.assert_called() + _, args, _ = call.mock_calls[0] + request_msg = ingestion_service.IngestAdEventsRequest() + assert args[0] == request_msg + + # This test is a coverage failsafe to make sure that totally empty calls, # i.e. request == None and no flattened fields passed, work. def test_retrieve_request_status_empty_call_rest(): @@ -3625,6 +4115,7 @@ def test_ingestion_service_base_transport(): "ingest_audience_members", "remove_audience_members", "ingest_events", + "ingest_ad_events", "retrieve_request_status", ) for method in methods: @@ -3900,6 +4391,9 @@ def test_ingestion_service_client_transport_session_collision(transport_name): session1 = client1.transport.ingest_events._session session2 = client2.transport.ingest_events._session assert session1 != session2 + session1 = client1.transport.ingest_ad_events._session + session2 = client2.transport.ingest_ad_events._session + assert session1 != session2 session1 = client1.transport.retrieve_request_status._session session2 = client2.transport.retrieve_request_status._session assert session1 != session2 diff --git a/packages/google-ads-datamanager/tests/unit/gapic/datamanager_v1/test_partner_link_service.py b/packages/google-ads-datamanager/tests/unit/gapic/datamanager_v1/test_partner_link_service.py index 16822b897a91..aae69c55e38b 100644 --- a/packages/google-ads-datamanager/tests/unit/gapic/datamanager_v1/test_partner_link_service.py +++ b/packages/google-ads-datamanager/tests/unit/gapic/datamanager_v1/test_partner_link_service.py @@ -1393,6 +1393,7 @@ def test_create_partner_link(request_type, transport: str = "grpc"): call.return_value = partner_link_service.PartnerLink( name="name_value", partner_link_id="partner_link_id_value", + feature_set=partner_link_service.FeatureSet.FEATURE_SET_AUDIENCE_AND_EVENT_MANAGEMENT, ) response = client.create_partner_link(request) @@ -1406,6 +1407,10 @@ def test_create_partner_link(request_type, transport: str = "grpc"): assert isinstance(response, partner_link_service.PartnerLink) assert response.name == "name_value" assert response.partner_link_id == "partner_link_id_value" + assert ( + response.feature_set + == partner_link_service.FeatureSet.FEATURE_SET_AUDIENCE_AND_EVENT_MANAGEMENT + ) def test_create_partner_link_non_empty_request_with_auto_populated_field(): @@ -1547,6 +1552,7 @@ async def test_create_partner_link_async(request_type, transport: str = "grpc_as partner_link_service.PartnerLink( name="name_value", partner_link_id="partner_link_id_value", + feature_set=partner_link_service.FeatureSet.FEATURE_SET_AUDIENCE_AND_EVENT_MANAGEMENT, ) ) response = await client.create_partner_link(request) @@ -1561,6 +1567,10 @@ async def test_create_partner_link_async(request_type, transport: str = "grpc_as assert isinstance(response, partner_link_service.PartnerLink) assert response.name == "name_value" assert response.partner_link_id == "partner_link_id_value" + assert ( + response.feature_set + == partner_link_service.FeatureSet.FEATURE_SET_AUDIENCE_AND_EVENT_MANAGEMENT + ) def test_create_partner_link_field_headers(): @@ -3440,6 +3450,7 @@ async def test_create_partner_link_empty_call_grpc_asyncio(): partner_link_service.PartnerLink( name="name_value", partner_link_id="partner_link_id_value", + feature_set=partner_link_service.FeatureSet.FEATURE_SET_AUDIENCE_AND_EVENT_MANAGEMENT, ) ) await client.create_partner_link(request=None) @@ -3559,6 +3570,13 @@ def test_create_partner_link_rest_call_success(request_type): "account_type": 1, }, "partner_account": {}, + "feature_set": 1, + "partner_customer_account": { + "account_id": "account_id_value", + "account_name": "account_name_value", + "account_type": "account_type_value", + }, + "partner_link_metadata": {"implicit_accounts": {}}, } # 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 @@ -3637,6 +3655,7 @@ def get_message_fields(field): return_value = partner_link_service.PartnerLink( name="name_value", partner_link_id="partner_link_id_value", + feature_set=partner_link_service.FeatureSet.FEATURE_SET_AUDIENCE_AND_EVENT_MANAGEMENT, ) # Wrap the value into a proper Response obj @@ -3655,6 +3674,10 @@ def get_message_fields(field): assert isinstance(response, partner_link_service.PartnerLink) assert response.name == "name_value" assert response.partner_link_id == "partner_link_id_value" + assert ( + response.feature_set + == partner_link_service.FeatureSet.FEATURE_SET_AUDIENCE_AND_EVENT_MANAGEMENT + ) @pytest.mark.parametrize("null_interceptor", [True, False]) diff --git a/packages/google-analytics-admin/google/analytics/admin/__init__.py b/packages/google-analytics-admin/google/analytics/admin/__init__.py index de58c7221942..53ca940df65d 100644 --- a/packages/google-analytics-admin/google/analytics/admin/__init__.py +++ b/packages/google-analytics-admin/google/analytics/admin/__init__.py @@ -236,6 +236,7 @@ UpdateMeasurementProtocolSecretRequest, UpdatePropertyRequest, UpdateReportingDataAnnotationRequest, + UpdateReportingIdentitySettingsRequest, UpdateSearchAds360LinkRequest, UpdateSKAdNetworkConversionValueSchemaRequest, UpdateSubpropertyEventFilterRequest, @@ -543,6 +544,7 @@ "UpdateMeasurementProtocolSecretRequest", "UpdatePropertyRequest", "UpdateReportingDataAnnotationRequest", + "UpdateReportingIdentitySettingsRequest", "UpdateSearchAds360LinkRequest", "UpdateSKAdNetworkConversionValueSchemaRequest", "UpdateSubpropertyEventFilterRequest", diff --git a/packages/google-analytics-admin/google/analytics/admin_v1alpha/__init__.py b/packages/google-analytics-admin/google/analytics/admin_v1alpha/__init__.py index d5044effcba8..c3bb19a1a3c0 100644 --- a/packages/google-analytics-admin/google/analytics/admin_v1alpha/__init__.py +++ b/packages/google-analytics-admin/google/analytics/admin_v1alpha/__init__.py @@ -239,6 +239,7 @@ UpdateMeasurementProtocolSecretRequest, UpdatePropertyRequest, UpdateReportingDataAnnotationRequest, + UpdateReportingIdentitySettingsRequest, UpdateSearchAds360LinkRequest, UpdateSKAdNetworkConversionValueSchemaRequest, UpdateSubpropertyEventFilterRequest, @@ -705,6 +706,7 @@ def _get_version(dependency_name): "UpdateMeasurementProtocolSecretRequest", "UpdatePropertyRequest", "UpdateReportingDataAnnotationRequest", + "UpdateReportingIdentitySettingsRequest", "UpdateSKAdNetworkConversionValueSchemaRequest", "UpdateSearchAds360LinkRequest", "UpdateSubpropertyEventFilterRequest", diff --git a/packages/google-analytics-admin/google/analytics/admin_v1alpha/gapic_metadata.json b/packages/google-analytics-admin/google/analytics/admin_v1alpha/gapic_metadata.json index 85e5a17017d0..5a249f54d896 100644 --- a/packages/google-analytics-admin/google/analytics/admin_v1alpha/gapic_metadata.json +++ b/packages/google-analytics-admin/google/analytics/admin_v1alpha/gapic_metadata.json @@ -765,6 +765,11 @@ "update_reporting_data_annotation" ] }, + "UpdateReportingIdentitySettings": { + "methods": [ + "update_reporting_identity_settings" + ] + }, "UpdateSKAdNetworkConversionValueSchema": { "methods": [ "update_sk_ad_network_conversion_value_schema" @@ -1545,6 +1550,11 @@ "update_reporting_data_annotation" ] }, + "UpdateReportingIdentitySettings": { + "methods": [ + "update_reporting_identity_settings" + ] + }, "UpdateSKAdNetworkConversionValueSchema": { "methods": [ "update_sk_ad_network_conversion_value_schema" @@ -2325,6 +2335,11 @@ "update_reporting_data_annotation" ] }, + "UpdateReportingIdentitySettings": { + "methods": [ + "update_reporting_identity_settings" + ] + }, "UpdateSKAdNetworkConversionValueSchema": { "methods": [ "update_sk_ad_network_conversion_value_schema" diff --git a/packages/google-analytics-admin/google/analytics/admin_v1alpha/services/analytics_admin_service/async_client.py b/packages/google-analytics-admin/google/analytics/admin_v1alpha/services/analytics_admin_service/async_client.py index 8fbc539b8990..a8bdb143f9e4 100644 --- a/packages/google-analytics-admin/google/analytics/admin_v1alpha/services/analytics_admin_service/async_client.py +++ b/packages/google-analytics-admin/google/analytics/admin_v1alpha/services/analytics_admin_service/async_client.py @@ -14759,6 +14759,121 @@ async def get_reporting_identity_settings( # Done; return the response. return response + async def update_reporting_identity_settings( + self, + request: Optional[ + Union[analytics_admin.UpdateReportingIdentitySettingsRequest, dict] + ] = None, + *, + reporting_identity_settings: Optional[ + resources.ReportingIdentitySettings + ] = 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, Union[str, bytes]]] = (), + ) -> resources.ReportingIdentitySettings: + r"""Updates the reporting identity settings for this + property. + + Args: + request (Optional[Union[google.analytics.admin_v1alpha.types.UpdateReportingIdentitySettingsRequest, dict]]): + The request object. Request message for + UpdateReportingIdentitySettings RPC. + reporting_identity_settings (:class:`google.analytics.admin_v1alpha.types.ReportingIdentitySettings`): + Required. The reporting identity settings to update. The + settings' ``name`` field is used to identify the + settings. + + This corresponds to the ``reporting_identity_settings`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + update_mask (:class:`google.protobuf.field_mask_pb2.FieldMask`): + Optional. The list of fields to be updated. Field names + must be in snake case (for example, "field_to_update"). + Omitted fields will not be updated. To replace the + entire entity, use one path with the string "\*" to + match all fields. If omitted, the service will treat it + as an implied field mask equivalent to all fields that + are populated. + + 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + google.analytics.admin_v1alpha.types.ReportingIdentitySettings: + A resource containing settings + related to reporting identity. + + """ + # 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. + flattened_params = [reporting_identity_settings, update_mask] + has_flattened_params = ( + len([param for param in flattened_params if param is not None]) > 0 + ) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance( + request, analytics_admin.UpdateReportingIdentitySettingsRequest + ): + request = analytics_admin.UpdateReportingIdentitySettingsRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if reporting_identity_settings is not None: + request.reporting_identity_settings = reporting_identity_settings + if update_mask is not None: + request.update_mask = update_mask + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.update_reporting_identity_settings + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + ( + ( + "reporting_identity_settings.name", + request.reporting_identity_settings.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_user_provided_data_settings( self, request: Optional[ diff --git a/packages/google-analytics-admin/google/analytics/admin_v1alpha/services/analytics_admin_service/client.py b/packages/google-analytics-admin/google/analytics/admin_v1alpha/services/analytics_admin_service/client.py index a9f002a47a4c..27b9051f4a8c 100644 --- a/packages/google-analytics-admin/google/analytics/admin_v1alpha/services/analytics_admin_service/client.py +++ b/packages/google-analytics-admin/google/analytics/admin_v1alpha/services/analytics_admin_service/client.py @@ -15355,6 +15355,120 @@ def get_reporting_identity_settings( # Done; return the response. return response + def update_reporting_identity_settings( + self, + request: Optional[ + Union[analytics_admin.UpdateReportingIdentitySettingsRequest, dict] + ] = None, + *, + reporting_identity_settings: Optional[ + resources.ReportingIdentitySettings + ] = 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, Union[str, bytes]]] = (), + ) -> resources.ReportingIdentitySettings: + r"""Updates the reporting identity settings for this + property. + + Args: + request (Union[google.analytics.admin_v1alpha.types.UpdateReportingIdentitySettingsRequest, dict]): + The request object. Request message for + UpdateReportingIdentitySettings RPC. + reporting_identity_settings (google.analytics.admin_v1alpha.types.ReportingIdentitySettings): + Required. The reporting identity settings to update. The + settings' ``name`` field is used to identify the + settings. + + This corresponds to the ``reporting_identity_settings`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + update_mask (google.protobuf.field_mask_pb2.FieldMask): + Optional. The list of fields to be updated. Field names + must be in snake case (for example, "field_to_update"). + Omitted fields will not be updated. To replace the + entire entity, use one path with the string "\*" to + match all fields. If omitted, the service will treat it + as an implied field mask equivalent to all fields that + are populated. + + 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + google.analytics.admin_v1alpha.types.ReportingIdentitySettings: + A resource containing settings + related to reporting identity. + + """ + # 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. + flattened_params = [reporting_identity_settings, update_mask] + has_flattened_params = ( + len([param for param in flattened_params if param is not None]) > 0 + ) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance( + request, analytics_admin.UpdateReportingIdentitySettingsRequest + ): + request = analytics_admin.UpdateReportingIdentitySettingsRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if reporting_identity_settings is not None: + request.reporting_identity_settings = reporting_identity_settings + 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_reporting_identity_settings + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + ( + ( + "reporting_identity_settings.name", + request.reporting_identity_settings.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_user_provided_data_settings( self, request: Optional[ diff --git a/packages/google-analytics-admin/google/analytics/admin_v1alpha/services/analytics_admin_service/transports/base.py b/packages/google-analytics-admin/google/analytics/admin_v1alpha/services/analytics_admin_service/transports/base.py index a17b0d30eb32..cc36ef0d8f6b 100644 --- a/packages/google-analytics-admin/google/analytics/admin_v1alpha/services/analytics_admin_service/transports/base.py +++ b/packages/google-analytics-admin/google/analytics/admin_v1alpha/services/analytics_admin_service/transports/base.py @@ -934,6 +934,11 @@ def _prep_wrapped_messages(self, client_info): default_timeout=None, client_info=client_info, ), + self.update_reporting_identity_settings: gapic_v1.method.wrap_method( + self.update_reporting_identity_settings, + default_timeout=None, + client_info=client_info, + ), self.get_user_provided_data_settings: gapic_v1.method.wrap_method( self.get_user_provided_data_settings, default_timeout=None, @@ -2573,6 +2578,18 @@ def get_reporting_identity_settings( ]: raise NotImplementedError() + @property + def update_reporting_identity_settings( + self, + ) -> Callable[ + [analytics_admin.UpdateReportingIdentitySettingsRequest], + Union[ + resources.ReportingIdentitySettings, + Awaitable[resources.ReportingIdentitySettings], + ], + ]: + raise NotImplementedError() + @property def get_user_provided_data_settings( self, diff --git a/packages/google-analytics-admin/google/analytics/admin_v1alpha/services/analytics_admin_service/transports/grpc.py b/packages/google-analytics-admin/google/analytics/admin_v1alpha/services/analytics_admin_service/transports/grpc.py index 3a7d2c6180b6..6c1dc0abdda4 100644 --- a/packages/google-analytics-admin/google/analytics/admin_v1alpha/services/analytics_admin_service/transports/grpc.py +++ b/packages/google-analytics-admin/google/analytics/admin_v1alpha/services/analytics_admin_service/transports/grpc.py @@ -4913,6 +4913,39 @@ def get_reporting_identity_settings( ) return self._stubs["get_reporting_identity_settings"] + @property + def update_reporting_identity_settings( + self, + ) -> Callable[ + [analytics_admin.UpdateReportingIdentitySettingsRequest], + resources.ReportingIdentitySettings, + ]: + r"""Return a callable for the update reporting identity + settings method over gRPC. + + Updates the reporting identity settings for this + property. + + Returns: + Callable[[~.UpdateReportingIdentitySettingsRequest], + ~.ReportingIdentitySettings]: + 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_reporting_identity_settings" not in self._stubs: + self._stubs["update_reporting_identity_settings"] = ( + self._logged_channel.unary_unary( + "/google.analytics.admin.v1alpha.AnalyticsAdminService/UpdateReportingIdentitySettings", + request_serializer=analytics_admin.UpdateReportingIdentitySettingsRequest.serialize, + response_deserializer=resources.ReportingIdentitySettings.deserialize, + ) + ) + return self._stubs["update_reporting_identity_settings"] + @property def get_user_provided_data_settings( self, diff --git a/packages/google-analytics-admin/google/analytics/admin_v1alpha/services/analytics_admin_service/transports/grpc_asyncio.py b/packages/google-analytics-admin/google/analytics/admin_v1alpha/services/analytics_admin_service/transports/grpc_asyncio.py index 55e85f98924f..e656c23c87c8 100644 --- a/packages/google-analytics-admin/google/analytics/admin_v1alpha/services/analytics_admin_service/transports/grpc_asyncio.py +++ b/packages/google-analytics-admin/google/analytics/admin_v1alpha/services/analytics_admin_service/transports/grpc_asyncio.py @@ -5027,6 +5027,39 @@ def get_reporting_identity_settings( ) return self._stubs["get_reporting_identity_settings"] + @property + def update_reporting_identity_settings( + self, + ) -> Callable[ + [analytics_admin.UpdateReportingIdentitySettingsRequest], + Awaitable[resources.ReportingIdentitySettings], + ]: + r"""Return a callable for the update reporting identity + settings method over gRPC. + + Updates the reporting identity settings for this + property. + + Returns: + Callable[[~.UpdateReportingIdentitySettingsRequest], + Awaitable[~.ReportingIdentitySettings]]: + 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_reporting_identity_settings" not in self._stubs: + self._stubs["update_reporting_identity_settings"] = ( + self._logged_channel.unary_unary( + "/google.analytics.admin.v1alpha.AnalyticsAdminService/UpdateReportingIdentitySettings", + request_serializer=analytics_admin.UpdateReportingIdentitySettingsRequest.serialize, + response_deserializer=resources.ReportingIdentitySettings.deserialize, + ) + ) + return self._stubs["update_reporting_identity_settings"] + @property def get_user_provided_data_settings( self, @@ -5833,6 +5866,11 @@ def _prep_wrapped_messages(self, client_info): default_timeout=None, client_info=client_info, ), + self.update_reporting_identity_settings: self._wrap_method( + self.update_reporting_identity_settings, + default_timeout=None, + client_info=client_info, + ), self.get_user_provided_data_settings: self._wrap_method( self.get_user_provided_data_settings, default_timeout=None, diff --git a/packages/google-analytics-admin/google/analytics/admin_v1alpha/services/analytics_admin_service/transports/rest.py b/packages/google-analytics-admin/google/analytics/admin_v1alpha/services/analytics_admin_service/transports/rest.py index c6724e97dd84..1d62fd255029 100644 --- a/packages/google-analytics-admin/google/analytics/admin_v1alpha/services/analytics_admin_service/transports/rest.py +++ b/packages/google-analytics-admin/google/analytics/admin_v1alpha/services/analytics_admin_service/transports/rest.py @@ -1189,6 +1189,14 @@ def post_update_reporting_data_annotation(self, response): logging.log(f"Received response: {response}") return response + def pre_update_reporting_identity_settings(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_update_reporting_identity_settings(self, response): + logging.log(f"Received response: {response}") + return response + def pre_update_search_ads360_link(self, request, metadata): logging.log(f"Received request: {request}") return request, metadata @@ -7851,6 +7859,57 @@ def post_update_reporting_data_annotation_with_metadata( """ return response, metadata + def pre_update_reporting_identity_settings( + self, + request: analytics_admin.UpdateReportingIdentitySettingsRequest, + metadata: Sequence[Tuple[str, Union[str, bytes]]], + ) -> Tuple[ + analytics_admin.UpdateReportingIdentitySettingsRequest, + Sequence[Tuple[str, Union[str, bytes]]], + ]: + """Pre-rpc interceptor for update_reporting_identity_settings + + Override in a subclass to manipulate the request or metadata + before they are sent to the AnalyticsAdminService server. + """ + return request, metadata + + def post_update_reporting_identity_settings( + self, response: resources.ReportingIdentitySettings + ) -> resources.ReportingIdentitySettings: + """Post-rpc interceptor for update_reporting_identity_settings + + DEPRECATED. Please use the `post_update_reporting_identity_settings_with_metadata` + interceptor instead. + + Override in a subclass to read or manipulate the response + after it is returned by the AnalyticsAdminService server but before + it is returned to user code. This `post_update_reporting_identity_settings` interceptor runs + before the `post_update_reporting_identity_settings_with_metadata` interceptor. + """ + return response + + def post_update_reporting_identity_settings_with_metadata( + self, + response: resources.ReportingIdentitySettings, + metadata: Sequence[Tuple[str, Union[str, bytes]]], + ) -> Tuple[ + resources.ReportingIdentitySettings, Sequence[Tuple[str, Union[str, bytes]]] + ]: + """Post-rpc interceptor for update_reporting_identity_settings + + Override in a subclass to read or manipulate the response or metadata after it + is returned by the AnalyticsAdminService server but before it is returned to user code. + + We recommend only using this `post_update_reporting_identity_settings_with_metadata` + interceptor in new development instead of the `post_update_reporting_identity_settings` interceptor. + When both interceptors are used, this `post_update_reporting_identity_settings_with_metadata` interceptor runs after the + `post_update_reporting_identity_settings` interceptor. The (possibly modified) response returned by + `post_update_reporting_identity_settings` will be passed to + `post_update_reporting_identity_settings_with_metadata`. + """ + return response, metadata + def pre_update_search_ads360_link( self, request: analytics_admin.UpdateSearchAds360LinkRequest, @@ -30462,6 +30521,169 @@ def __call__( ) return resp + class _UpdateReportingIdentitySettings( + _BaseAnalyticsAdminServiceRestTransport._BaseUpdateReportingIdentitySettings, + AnalyticsAdminServiceRestStub, + ): + def __hash__(self): + return hash( + "AnalyticsAdminServiceRestTransport.UpdateReportingIdentitySettings" + ) + + @staticmethod + def _get_response( + host, + metadata, + query_params, + session, + timeout, + transcoded_request, + body=None, + ): + uri = transcoded_request["uri"] + method = transcoded_request["method"] + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(session, method)( + "{host}{uri}".format(host=host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + data=body, + ) + return response + + def __call__( + self, + request: analytics_admin.UpdateReportingIdentitySettingsRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> resources.ReportingIdentitySettings: + r"""Call the update reporting identity + settings method over HTTP. + + Args: + request (~.analytics_admin.UpdateReportingIdentitySettingsRequest): + The request object. Request message for + UpdateReportingIdentitySettings RPC. + 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + ~.resources.ReportingIdentitySettings: + A resource containing settings + related to reporting identity. + + """ + + http_options = _BaseAnalyticsAdminServiceRestTransport._BaseUpdateReportingIdentitySettings._get_http_options() + + request, metadata = ( + self._interceptor.pre_update_reporting_identity_settings( + request, metadata + ) + ) + transcoded_request = _BaseAnalyticsAdminServiceRestTransport._BaseUpdateReportingIdentitySettings._get_transcoded_request( + http_options, request + ) + + body = _BaseAnalyticsAdminServiceRestTransport._BaseUpdateReportingIdentitySettings._get_request_body_json( + transcoded_request + ) + + # Jsonify the query params + query_params = _BaseAnalyticsAdminServiceRestTransport._BaseUpdateReportingIdentitySettings._get_query_params_json( + transcoded_request + ) + + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + logging.DEBUG + ): # pragma: NO COVER + request_url = "{host}{uri}".format( + host=self._host, uri=transcoded_request["uri"] + ) + method = transcoded_request["method"] + try: + request_payload = type(request).to_json(request) + except: + request_payload = None + http_request = { + "payload": request_payload, + "requestMethod": method, + "requestUrl": request_url, + "headers": dict(metadata), + } + _LOGGER.debug( + f"Sending request for google.analytics.admin_v1alpha.AnalyticsAdminServiceClient.UpdateReportingIdentitySettings", + extra={ + "serviceName": "google.analytics.admin.v1alpha.AnalyticsAdminService", + "rpcName": "UpdateReportingIdentitySettings", + "httpRequest": http_request, + "metadata": http_request["headers"], + }, + ) + + # Send the request + response = AnalyticsAdminServiceRestTransport._UpdateReportingIdentitySettings._get_response( + self._host, + metadata, + query_params, + self._session, + timeout, + transcoded_request, + 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 = resources.ReportingIdentitySettings() + pb_resp = resources.ReportingIdentitySettings.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + + resp = self._interceptor.post_update_reporting_identity_settings(resp) + response_metadata = [(k, str(v)) for k, v in response.headers.items()] + resp, _ = ( + self._interceptor.post_update_reporting_identity_settings_with_metadata( + resp, response_metadata + ) + ) + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + logging.DEBUG + ): # pragma: NO COVER + try: + response_payload = resources.ReportingIdentitySettings.to_json( + response + ) + except: + response_payload = None + http_response = { + "payload": response_payload, + "headers": dict(response.headers), + "status": response.status_code, + } + _LOGGER.debug( + "Received response for google.analytics.admin_v1alpha.AnalyticsAdminServiceClient.update_reporting_identity_settings", + extra={ + "serviceName": "google.analytics.admin.v1alpha.AnalyticsAdminService", + "rpcName": "UpdateReportingIdentitySettings", + "metadata": http_response["headers"], + "httpResponse": http_response, + }, + ) + return resp + class _UpdateSearchAds360Link( _BaseAnalyticsAdminServiceRestTransport._BaseUpdateSearchAds360Link, AnalyticsAdminServiceRestStub, @@ -32720,6 +32942,19 @@ def update_reporting_data_annotation( self._session, self._host, self._interceptor ) # type: ignore + @property + def update_reporting_identity_settings( + self, + ) -> Callable[ + [analytics_admin.UpdateReportingIdentitySettingsRequest], + resources.ReportingIdentitySettings, + ]: + # 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._UpdateReportingIdentitySettings( + self._session, self._host, self._interceptor + ) # type: ignore + @property def update_search_ads360_link( self, diff --git a/packages/google-analytics-admin/google/analytics/admin_v1alpha/services/analytics_admin_service/transports/rest_base.py b/packages/google-analytics-admin/google/analytics/admin_v1alpha/services/analytics_admin_service/transports/rest_base.py index 5b9a0ac7f71d..999cb5db9778 100644 --- a/packages/google-analytics-admin/google/analytics/admin_v1alpha/services/analytics_admin_service/transports/rest_base.py +++ b/packages/google-analytics-admin/google/analytics/admin_v1alpha/services/analytics_admin_service/transports/rest_base.py @@ -7959,6 +7959,65 @@ def _get_query_params_json(transcoded_request): query_params["$alt"] = "json;enum-encoding=int" return query_params + class _BaseUpdateReportingIdentitySettings: + def __hash__(self): # pragma: NO COVER + return NotImplementedError("__hash__ must be implemented.") + + __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 + } + + @staticmethod + def _get_http_options(): + http_options: List[Dict[str, str]] = [ + { + "method": "patch", + "uri": "/v1alpha/{reporting_identity_settings.name=properties/*/reportingIdentitySettings}", + "body": "reporting_identity_settings", + }, + ] + return http_options + + @staticmethod + def _get_transcoded_request(http_options, request): + pb_request = analytics_admin.UpdateReportingIdentitySettingsRequest.pb( + request + ) + transcoded_request = path_template.transcode(http_options, pb_request) + return transcoded_request + + @staticmethod + def _get_request_body_json(transcoded_request): + # Jsonify the request body + + body = json_format.MessageToJson( + transcoded_request["body"], use_integers_for_enums=True + ) + return body + + @staticmethod + def _get_query_params_json(transcoded_request): + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + use_integers_for_enums=True, + ) + ) + query_params.update( + _BaseAnalyticsAdminServiceRestTransport._BaseUpdateReportingIdentitySettings._get_unset_required_fields( + query_params + ) + ) + + query_params["$alt"] = "json;enum-encoding=int" + return query_params + class _BaseUpdateSearchAds360Link: def __hash__(self): # pragma: NO COVER return NotImplementedError("__hash__ must be implemented.") diff --git a/packages/google-analytics-admin/google/analytics/admin_v1alpha/types/__init__.py b/packages/google-analytics-admin/google/analytics/admin_v1alpha/types/__init__.py index 1681a970339f..825af3013797 100644 --- a/packages/google-analytics-admin/google/analytics/admin_v1alpha/types/__init__.py +++ b/packages/google-analytics-admin/google/analytics/admin_v1alpha/types/__init__.py @@ -225,6 +225,7 @@ UpdateMeasurementProtocolSecretRequest, UpdatePropertyRequest, UpdateReportingDataAnnotationRequest, + UpdateReportingIdentitySettingsRequest, UpdateSearchAds360LinkRequest, UpdateSKAdNetworkConversionValueSchemaRequest, UpdateSubpropertyEventFilterRequest, @@ -530,6 +531,7 @@ "UpdateMeasurementProtocolSecretRequest", "UpdatePropertyRequest", "UpdateReportingDataAnnotationRequest", + "UpdateReportingIdentitySettingsRequest", "UpdateSearchAds360LinkRequest", "UpdateSKAdNetworkConversionValueSchemaRequest", "UpdateSubpropertyEventFilterRequest", diff --git a/packages/google-analytics-admin/google/analytics/admin_v1alpha/types/analytics_admin.py b/packages/google-analytics-admin/google/analytics/admin_v1alpha/types/analytics_admin.py index 5ae43add0792..cf6b1913fdde 100644 --- a/packages/google-analytics-admin/google/analytics/admin_v1alpha/types/analytics_admin.py +++ b/packages/google-analytics-admin/google/analytics/admin_v1alpha/types/analytics_admin.py @@ -231,6 +231,7 @@ "ListSubpropertySyncConfigsResponse", "UpdateSubpropertySyncConfigRequest", "GetReportingIdentitySettingsRequest", + "UpdateReportingIdentitySettingsRequest", "GetUserProvidedDataSettingsRequest", }, ) @@ -5235,6 +5236,34 @@ class GetReportingIdentitySettingsRequest(proto.Message): ) +class UpdateReportingIdentitySettingsRequest(proto.Message): + r"""Request message for UpdateReportingIdentitySettings RPC. + + Attributes: + reporting_identity_settings (google.analytics.admin_v1alpha.types.ReportingIdentitySettings): + Required. The reporting identity settings to update. The + settings' ``name`` field is used to identify the settings. + update_mask (google.protobuf.field_mask_pb2.FieldMask): + Optional. The list of fields to be updated. Field names must + be in snake case (for example, "field_to_update"). Omitted + fields will not be updated. To replace the entire entity, + use one path with the string "\*" to match all fields. If + omitted, the service will treat it as an implied field mask + equivalent to all fields that are populated. + """ + + reporting_identity_settings: resources.ReportingIdentitySettings = proto.Field( + proto.MESSAGE, + number=1, + message=resources.ReportingIdentitySettings, + ) + update_mask: field_mask_pb2.FieldMask = proto.Field( + proto.MESSAGE, + number=2, + message=field_mask_pb2.FieldMask, + ) + + class GetUserProvidedDataSettingsRequest(proto.Message): r"""Request message for GetUserProvidedDataSettings RPC diff --git a/packages/google-analytics-admin/google/analytics/admin_v1alpha/types/resources.py b/packages/google-analytics-admin/google/analytics/admin_v1alpha/types/resources.py index f32b4ab50f10..3a53e79b8ad6 100644 --- a/packages/google-analytics-admin/google/analytics/admin_v1alpha/types/resources.py +++ b/packages/google-analytics-admin/google/analytics/admin_v1alpha/types/resources.py @@ -1135,6 +1135,9 @@ class PropertySummary(proto.Message): change the parent. Format: accounts/{account}, properties/{property} Example: "accounts/100", "properties/200". + can_edit (bool): + If true, then the user has a Google Analytics + role that permits them to edit the property. """ property: str = proto.Field( @@ -1154,6 +1157,10 @@ class PropertySummary(proto.Message): proto.STRING, number=4, ) + can_edit: bool = proto.Field( + proto.BOOL, + number=5, + ) class MeasurementProtocolSecret(proto.Message): diff --git a/packages/google-analytics-admin/google/analytics/admin_v1beta/types/analytics_admin.py b/packages/google-analytics-admin/google/analytics/admin_v1beta/types/analytics_admin.py index 65e1f577b905..e8098788e9e7 100644 --- a/packages/google-analytics-admin/google/analytics/admin_v1beta/types/analytics_admin.py +++ b/packages/google-analytics-admin/google/analytics/admin_v1beta/types/analytics_admin.py @@ -347,18 +347,18 @@ class ListAccountsRequest(proto.Message): Attributes: page_size (int): - The maximum number of resources to return. - The service may return fewer than this value, - even if there are additional pages. If + Optional. The maximum number of resources to + return. The service may return fewer than this + value, even if there are additional pages. If unspecified, at most 50 resources will be returned. The maximum value is 200; (higher values will be coerced to the maximum) page_token (str): - A page token, received from a previous ``ListAccounts`` - call. Provide this to retrieve the subsequent page. When - paginating, all other parameters provided to - ``ListAccounts`` must match the call that provided the page - token. + Optional. A page token, received from a previous + ``ListAccounts`` call. Provide this to retrieve the + subsequent page. When paginating, all other parameters + provided to ``ListAccounts`` must match the call that + provided the page token. show_deleted (bool): Whether to include soft-deleted (ie: "trashed") Accounts in the results. Accounts can @@ -524,18 +524,18 @@ class ListPropertiesRequest(proto.Message): | firebase_project:project-id | The firebase project with id: project-id. | | firebase_project:123 | The firebase project with number: 123. | page_size (int): - The maximum number of resources to return. - The service may return fewer than this value, - even if there are additional pages. If + Optional. The maximum number of resources to + return. The service may return fewer than this + value, even if there are additional pages. If unspecified, at most 50 resources will be returned. The maximum value is 200; (higher values will be coerced to the maximum) page_token (str): - A page token, received from a previous ``ListProperties`` - call. Provide this to retrieve the subsequent page. When - paginating, all other parameters provided to - ``ListProperties`` must match the call that provided the - page token. + Optional. A page token, received from a previous + ``ListProperties`` call. Provide this to retrieve the + subsequent page. When paginating, all other parameters + provided to ``ListProperties`` must match the call that + provided the page token. show_deleted (bool): Whether to include soft-deleted (ie: "trashed") Properties in the results. Properties @@ -696,18 +696,18 @@ class ListFirebaseLinksRequest(proto.Message): Example: ``properties/1234`` page_size (int): - The maximum number of resources to return. - The service may return fewer than this value, - even if there are additional pages. If + Optional. The maximum number of resources to + return. The service may return fewer than this + value, even if there are additional pages. If unspecified, at most 50 resources will be returned. The maximum value is 200; (higher values will be coerced to the maximum) page_token (str): - A page token, received from a previous ``ListFirebaseLinks`` - call. Provide this to retrieve the subsequent page. When - paginating, all other parameters provided to - ``ListFirebaseLinks`` must match the call that provided the - page token. + Optional. A page token, received from a previous + ``ListFirebaseLinks`` call. Provide this to retrieve the + subsequent page. When paginating, all other parameters + provided to ``ListFirebaseLinks`` must match the call that + provided the page token. """ parent: str = proto.Field( @@ -821,12 +821,12 @@ class ListGoogleAdsLinksRequest(proto.Message): parent (str): Required. Example format: properties/1234 page_size (int): - The maximum number of resources to return. - If unspecified, at most 50 resources will be - returned. The maximum value is 200 (higher - values will be coerced to the maximum). + Optional. The maximum number of resources to + return. If unspecified, at most 50 resources + will be returned. The maximum value is 200 + (higher values will be coerced to the maximum). page_token (str): - A page token, received from a previous + Optional. A page token, received from a previous ``ListGoogleAdsLinks`` call. Provide this to retrieve the subsequent page. @@ -898,15 +898,15 @@ class ListAccountSummariesRequest(proto.Message): Attributes: page_size (int): - The maximum number of AccountSummary - resources to return. The service may return - fewer than this value, even if there are - additional pages. If unspecified, at most 50 + Optional. The maximum number of + AccountSummary resources to return. The service + may return fewer than this value, even if there + are additional pages. If unspecified, at most 50 resources will be returned. The maximum value is 200; (higher values will be coerced to the maximum) page_token (str): - A page token, received from a previous + Optional. A page token, received from a previous ``ListAccountSummaries`` call. Provide this to retrieve the subsequent page. When paginating, all other parameters provided to ``ListAccountSummaries`` must match the call @@ -1203,12 +1203,12 @@ class ListMeasurementProtocolSecretsRequest(proto.Message): properties/{property}/dataStreams/{dataStream}/measurementProtocolSecrets page_size (int): - The maximum number of resources to return. - If unspecified, at most 10 resources will be - returned. The maximum value is 10. Higher values - will be coerced to the maximum. + Optional. The maximum number of resources to + return. If unspecified, at most 10 resources + will be returned. The maximum value is 10. + Higher values will be coerced to the maximum. page_token (str): - A page token, received from a previous + Optional. A page token, received from a previous ``ListMeasurementProtocolSecrets`` call. Provide this to retrieve the subsequent page. When paginating, all other parameters provided to ``ListMeasurementProtocolSecrets`` @@ -1350,12 +1350,12 @@ class ListConversionEventsRequest(proto.Message): Required. The resource name of the parent property. Example: 'properties/123' page_size (int): - The maximum number of resources to return. - If unspecified, at most 50 resources will be - returned. The maximum value is 200; (higher - values will be coerced to the maximum) + Optional. The maximum number of resources to + return. If unspecified, at most 50 resources + will be returned. The maximum value is 200; + (higher values will be coerced to the maximum) page_token (str): - A page token, received from a previous + Optional. A page token, received from a previous ``ListConversionEvents`` call. Provide this to retrieve the subsequent page. When paginating, all other parameters provided to ``ListConversionEvents`` must match the call @@ -1492,16 +1492,16 @@ class ListKeyEventsRequest(proto.Message): Required. The resource name of the parent property. Example: 'properties/123' page_size (int): - The maximum number of resources to return. - If unspecified, at most 50 resources will be - returned. The maximum value is 200; (higher - values will be coerced to the maximum) + Optional. The maximum number of resources to + return. If unspecified, at most 50 resources + will be returned. The maximum value is 200; + (higher values will be coerced to the maximum) page_token (str): - A page token, received from a previous ``ListKeyEvents`` - call. Provide this to retrieve the subsequent page. When - paginating, all other parameters provided to - ``ListKeyEvents`` must match the call that provided the page - token. + Optional. A page token, received from a previous + ``ListKeyEvents`` call. Provide this to retrieve the + subsequent page. When paginating, all other parameters + provided to ``ListKeyEvents`` must match the call that + provided the page token. """ parent: str = proto.Field( @@ -1597,12 +1597,12 @@ class ListCustomDimensionsRequest(proto.Message): parent (str): Required. Example format: properties/1234 page_size (int): - The maximum number of resources to return. - If unspecified, at most 50 resources will be - returned. The maximum value is 200 (higher - values will be coerced to the maximum). + Optional. The maximum number of resources to + return. If unspecified, at most 50 resources + will be returned. The maximum value is 200 + (higher values will be coerced to the maximum). page_token (str): - A page token, received from a previous + Optional. A page token, received from a previous ``ListCustomDimensions`` call. Provide this to retrieve the subsequent page. diff --git a/packages/google-analytics-admin/google/analytics/admin_v1beta/types/resources.py b/packages/google-analytics-admin/google/analytics/admin_v1beta/types/resources.py index bdc45acd752f..ab758a47989a 100644 --- a/packages/google-analytics-admin/google/analytics/admin_v1beta/types/resources.py +++ b/packages/google-analytics-admin/google/analytics/admin_v1beta/types/resources.py @@ -280,7 +280,7 @@ class Account(proto.Message): Attributes: name (str): - Output only. Resource name of this account. + Identifier. Resource name of this account. Format: accounts/{account} Example: "accounts/100". create_time (google.protobuf.timestamp_pb2.Timestamp): @@ -344,7 +344,7 @@ class Property(proto.Message): Attributes: name (str): - Output only. Resource name of this property. Format: + Identifier. Resource name of this property. Format: properties/{property_id} Example: "properties/1000". property_type (google.analytics.admin_v1beta.types.PropertyType): Immutable. The property type for this Property resource. @@ -493,7 +493,7 @@ class DataStream(proto.Message): This field is a member of `oneof`_ ``stream_data``. name (str): - Output only. Resource name of this Data Stream. Format: + Identifier. Resource name of this Data Stream. Format: properties/{property_id}/dataStreams/{stream_id} Example: "properties/1000/dataStreams/2000". type_ (google.analytics.admin_v1beta.types.DataStream.DataStreamType): @@ -658,7 +658,7 @@ class FirebaseLink(proto.Message): Attributes: name (str): - Output only. Example format: + Identifier. Example format: properties/1234/firebaseLinks/5678 project (str): Immutable. Firebase project resource name. When creating a @@ -694,7 +694,7 @@ class GoogleAdsLink(proto.Message): Attributes: name (str): - Output only. Format: + Identifier. Format: properties/{propertyId}/googleAdsLinks/{googleAdsLinkId} @@ -765,28 +765,53 @@ class DataSharingSettings(proto.Message): Attributes: name (str): - Output only. Resource name. + Identifier. Resource name. Format: accounts/{account}/dataSharingSettings Example: "accounts/1000/dataSharingSettings". sharing_with_google_support_enabled (bool): - Allows Google support to access the data in - order to help troubleshoot issues. + Allows Google technical support + representatives access to your Google Analytics + data and account when necessary to provide + service and find solutions to technical issues. + + This field maps to the "Technical support" field + in the Google Analytics Admin UI. sharing_with_google_assigned_sales_enabled (bool): - Allows Google sales teams that are assigned - to the customer to access the data in order to - suggest configuration changes to improve - results. Sales team restrictions still apply - when enabled. + Allows Google access to your Google Analytics + account data, including account usage and + configuration data, product spending, and users + associated with your Google Analytics account, + so that Google can help you make the most of + Google products, providing you with insights, + offers, recommendations, and optimization tips + across Google Analytics and other Google + products for business. + + This field maps to the "Recommendations for your + business" field in the Google Analytics Admin + UI. sharing_with_google_any_sales_enabled (bool): - Allows any of Google sales to access the data - in order to suggest configuration changes to - improve results. + Deprecated. This field is no longer used and + always returns false. sharing_with_google_products_enabled (bool): Allows Google to use the data to improve other Google products or services. + This fields maps to the "Google products & + services" field in the Google Analytics Admin + UI. sharing_with_others_enabled (bool): - Allows Google to share the data anonymously - in aggregate form with others. + Enable features like predictions, modeled + data, and benchmarking that can provide you with + richer business insights when you contribute + aggregated measurement data. The data you share + (including information about the property from + which it is shared) is aggregated and + de-identified before being used to generate + business insights. + + This field maps to the "Modeling contributions & + business insights" field in the Google Analytics + Admin UI. """ name: str = proto.Field( @@ -821,7 +846,7 @@ class AccountSummary(proto.Message): Attributes: name (str): - Resource name for this account summary. Format: + Identifier. Resource name for this account summary. Format: accountSummaries/{account_id} Example: "accountSummaries/1000". account (str): @@ -875,6 +900,9 @@ class PropertySummary(proto.Message): change the parent. Format: accounts/{account}, properties/{property} Example: "accounts/100", "properties/200". + can_edit (bool): + If true, then the user has a Google Analytics + role that permits them to edit the property. """ property: str = proto.Field( @@ -894,6 +922,10 @@ class PropertySummary(proto.Message): proto.STRING, number=4, ) + can_edit: bool = proto.Field( + proto.BOOL, + number=5, + ) class MeasurementProtocolSecret(proto.Message): @@ -901,7 +933,7 @@ class MeasurementProtocolSecret(proto.Message): Attributes: name (str): - Output only. Resource name of this secret. + Identifier. Resource name of this secret. This secret may be a child of any type of stream. Format: @@ -1142,7 +1174,7 @@ class ConversionEvent(proto.Message): Attributes: name (str): - Output only. Resource name of this conversion event. Format: + Identifier. Resource name of this conversion event. Format: properties/{property}/conversionEvents/{conversion_event} event_name (str): Immutable. The event name for this conversion @@ -1381,7 +1413,7 @@ class CustomDimension(proto.Message): Attributes: name (str): - Output only. Resource name for this + Identifier. Resource name for this CustomDimension resource. Format: properties/{property}/customDimensions/{customDimension} parameter_name (str): @@ -1473,7 +1505,7 @@ class CustomMetric(proto.Message): Attributes: name (str): - Output only. Resource name for this + Identifier. Resource name for this CustomMetric resource. Format: properties/{property}/customMetrics/{customMetric} parameter_name (str): @@ -1621,7 +1653,7 @@ class DataRetentionSettings(proto.Message): Attributes: name (str): - Output only. Resource name for this + Identifier. Resource name for this DataRetentionSetting resource. Format: properties/{property}/dataRetentionSettings event_data_retention (google.analytics.admin_v1beta.types.DataRetentionSettings.RetentionDuration): diff --git a/packages/google-analytics-admin/tests/unit/gapic/admin_v1alpha/test_analytics_admin_service.py b/packages/google-analytics-admin/tests/unit/gapic/admin_v1alpha/test_analytics_admin_service.py index 45ff53758cf3..d2e8861de9b1 100644 --- a/packages/google-analytics-admin/tests/unit/gapic/admin_v1alpha/test_analytics_admin_service.py +++ b/packages/google-analytics-admin/tests/unit/gapic/admin_v1alpha/test_analytics_admin_service.py @@ -59714,6 +59714,375 @@ async def test_get_reporting_identity_settings_flattened_error_async(): ) +@pytest.mark.parametrize( + "request_type", + [ + analytics_admin.UpdateReportingIdentitySettingsRequest(), + {}, + ], +) +def test_update_reporting_identity_settings(request_type, transport: str = "grpc"): + client = AnalyticsAdminServiceClient( + 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_reporting_identity_settings), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = resources.ReportingIdentitySettings( + name="name_value", + reporting_identity=resources.ReportingIdentitySettings.ReportingIdentity.BLENDED, + ) + response = client.update_reporting_identity_settings(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = analytics_admin.UpdateReportingIdentitySettingsRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, resources.ReportingIdentitySettings) + assert response.name == "name_value" + assert ( + response.reporting_identity + == resources.ReportingIdentitySettings.ReportingIdentity.BLENDED + ) + + +def test_update_reporting_identity_settings_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 = AnalyticsAdminServiceClient( + 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 = analytics_admin.UpdateReportingIdentitySettingsRequest() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_reporting_identity_settings), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.update_reporting_identity_settings(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + request_msg = analytics_admin.UpdateReportingIdentitySettingsRequest() + assert args[0] == request_msg + + +def test_update_reporting_identity_settings_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = AnalyticsAdminServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.update_reporting_identity_settings + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.update_reporting_identity_settings + ] = mock_rpc + request = {} + client.update_reporting_identity_settings(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.update_reporting_identity_settings(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_update_reporting_identity_settings_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = AnalyticsAdminServiceAsyncClient( + credentials=async_anonymous_credentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.update_reporting_identity_settings + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.AsyncMock() + mock_rpc.return_value = mock.Mock() + client._client._transport._wrapped_methods[ + client._client._transport.update_reporting_identity_settings + ] = mock_rpc + + request = {} + await client.update_reporting_identity_settings(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + await client.update_reporting_identity_settings(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +@pytest.mark.parametrize( + "request_type", + [ + analytics_admin.UpdateReportingIdentitySettingsRequest(), + {}, + ], +) +async def test_update_reporting_identity_settings_async( + request_type, transport: str = "grpc_asyncio" +): + client = AnalyticsAdminServiceAsyncClient( + credentials=async_anonymous_credentials(), + 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_reporting_identity_settings), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + resources.ReportingIdentitySettings( + name="name_value", + reporting_identity=resources.ReportingIdentitySettings.ReportingIdentity.BLENDED, + ) + ) + response = await client.update_reporting_identity_settings(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = analytics_admin.UpdateReportingIdentitySettingsRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, resources.ReportingIdentitySettings) + assert response.name == "name_value" + assert ( + response.reporting_identity + == resources.ReportingIdentitySettings.ReportingIdentity.BLENDED + ) + + +def test_update_reporting_identity_settings_field_headers(): + client = AnalyticsAdminServiceClient( + 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 = analytics_admin.UpdateReportingIdentitySettingsRequest() + + request.reporting_identity_settings.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_reporting_identity_settings), "__call__" + ) as call: + call.return_value = resources.ReportingIdentitySettings() + client.update_reporting_identity_settings(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", + "reporting_identity_settings.name=name_value", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_update_reporting_identity_settings_field_headers_async(): + client = AnalyticsAdminServiceAsyncClient( + credentials=async_anonymous_credentials(), + ) + + # 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 = analytics_admin.UpdateReportingIdentitySettingsRequest() + + request.reporting_identity_settings.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_reporting_identity_settings), "__call__" + ) as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + resources.ReportingIdentitySettings() + ) + await client.update_reporting_identity_settings(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", + "reporting_identity_settings.name=name_value", + ) in kw["metadata"] + + +def test_update_reporting_identity_settings_flattened(): + client = AnalyticsAdminServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_reporting_identity_settings), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = resources.ReportingIdentitySettings() + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.update_reporting_identity_settings( + reporting_identity_settings=resources.ReportingIdentitySettings( + 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].reporting_identity_settings + mock_val = resources.ReportingIdentitySettings(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_reporting_identity_settings_flattened_error(): + client = AnalyticsAdminServiceClient( + 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_reporting_identity_settings( + analytics_admin.UpdateReportingIdentitySettingsRequest(), + reporting_identity_settings=resources.ReportingIdentitySettings( + name="name_value" + ), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + +@pytest.mark.asyncio +async def test_update_reporting_identity_settings_flattened_async(): + client = AnalyticsAdminServiceAsyncClient( + credentials=async_anonymous_credentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.update_reporting_identity_settings), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = resources.ReportingIdentitySettings() + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + resources.ReportingIdentitySettings() + ) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.update_reporting_identity_settings( + reporting_identity_settings=resources.ReportingIdentitySettings( + 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].reporting_identity_settings + mock_val = resources.ReportingIdentitySettings(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_reporting_identity_settings_flattened_error_async(): + client = AnalyticsAdminServiceAsyncClient( + credentials=async_anonymous_credentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + await client.update_reporting_identity_settings( + analytics_admin.UpdateReportingIdentitySettingsRequest(), + reporting_identity_settings=resources.ReportingIdentitySettings( + name="name_value" + ), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + @pytest.mark.parametrize( "request_type", [ @@ -89851,6 +90220,203 @@ def test_get_reporting_identity_settings_rest_flattened_error(transport: str = " ) +def test_update_reporting_identity_settings_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = AnalyticsAdminServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.update_reporting_identity_settings + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.update_reporting_identity_settings + ] = mock_rpc + + request = {} + client.update_reporting_identity_settings(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.update_reporting_identity_settings(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_update_reporting_identity_settings_rest_required_fields( + request_type=analytics_admin.UpdateReportingIdentitySettingsRequest, +): + transport_class = transports.AnalyticsAdminServiceRestTransport + + 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_reporting_identity_settings._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_reporting_identity_settings._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 = AnalyticsAdminServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = resources.ReportingIdentitySettings() + # 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 = resources.ReportingIdentitySettings.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 + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + + response = client.update_reporting_identity_settings(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert sorted(expected_params) == sorted(actual_params) + + +def test_update_reporting_identity_settings_rest_unset_required_fields(): + transport = transports.AnalyticsAdminServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = ( + transport.update_reporting_identity_settings._get_unset_required_fields({}) + ) + assert set(unset_fields) == ( + set(("updateMask",)) & set(("reportingIdentitySettings",)) + ) + + +def test_update_reporting_identity_settings_rest_flattened(): + client = AnalyticsAdminServiceClient( + 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 = resources.ReportingIdentitySettings() + + # get arguments that satisfy an http rule for this method + sample_request = { + "reporting_identity_settings": { + "name": "properties/sample1/reportingIdentitySettings" + } + } + + # get truthy value for each flattened field + mock_args = dict( + reporting_identity_settings=resources.ReportingIdentitySettings( + 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 = resources.ReportingIdentitySettings.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 + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + + client.update_reporting_identity_settings(**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/{reporting_identity_settings.name=properties/*/reportingIdentitySettings}" + % client.transport._host, + args[1], + ) + + +def test_update_reporting_identity_settings_rest_flattened_error( + transport: str = "rest", +): + client = AnalyticsAdminServiceClient( + 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_reporting_identity_settings( + analytics_admin.UpdateReportingIdentitySettingsRequest(), + reporting_identity_settings=resources.ReportingIdentitySettings( + name="name_value" + ), + update_mask=field_mask_pb2.FieldMask(paths=["paths_value"]), + ) + + def test_get_user_provided_data_settings_rest_use_cached_wrapped_rpc(): # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, # instead of constructing them on each call @@ -93511,6 +94077,28 @@ def test_get_reporting_identity_settings_empty_call_grpc(): assert args[0] == request_msg +# This test is a coverage failsafe to make sure that totally empty calls, +# i.e. request == None and no flattened fields passed, work. +def test_update_reporting_identity_settings_empty_call_grpc(): + client = AnalyticsAdminServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Mock the actual call, and fake the request. + with mock.patch.object( + type(client.transport.update_reporting_identity_settings), "__call__" + ) as call: + call.return_value = resources.ReportingIdentitySettings() + client.update_reporting_identity_settings(request=None) + + # Establish that the underlying stub method was called. + call.assert_called() + _, args, _ = call.mock_calls[0] + request_msg = analytics_admin.UpdateReportingIdentitySettingsRequest() + assert args[0] == request_msg + + # This test is a coverage failsafe to make sure that totally empty calls, # i.e. request == None and no flattened fields passed, work. def test_get_user_provided_data_settings_empty_call_grpc(): @@ -98035,6 +98623,35 @@ async def test_get_reporting_identity_settings_empty_call_grpc_asyncio(): assert args[0] == request_msg +# This test is a coverage failsafe to make sure that totally empty calls, +# i.e. request == None and no flattened fields passed, work. +@pytest.mark.asyncio +async def test_update_reporting_identity_settings_empty_call_grpc_asyncio(): + client = AnalyticsAdminServiceAsyncClient( + credentials=async_anonymous_credentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call, and fake the request. + with mock.patch.object( + type(client.transport.update_reporting_identity_settings), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + resources.ReportingIdentitySettings( + name="name_value", + reporting_identity=resources.ReportingIdentitySettings.ReportingIdentity.BLENDED, + ) + ) + await client.update_reporting_identity_settings(request=None) + + # Establish that the underlying stub method was called. + call.assert_called() + _, args, _ = call.mock_calls[0] + request_msg = analytics_admin.UpdateReportingIdentitySettingsRequest() + assert args[0] == request_msg + + # This test is a coverage failsafe to make sure that totally empty calls, # i.e. request == None and no flattened fields passed, work. @pytest.mark.asyncio @@ -123640,6 +124257,234 @@ def test_get_reporting_identity_settings_rest_interceptors(null_interceptor): post_with_metadata.assert_called_once() +def test_update_reporting_identity_settings_rest_bad_request( + request_type=analytics_admin.UpdateReportingIdentitySettingsRequest, +): + client = AnalyticsAdminServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + # send a request that will satisfy transcoding + request_init = { + "reporting_identity_settings": { + "name": "properties/sample1/reportingIdentitySettings" + } + } + 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 = mock.Mock() + json_return_value = "" + response_value.json = mock.Mock(return_value={}) + response_value.status_code = 400 + response_value.request = mock.Mock() + req.return_value = response_value + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + client.update_reporting_identity_settings(request) + + +@pytest.mark.parametrize( + "request_type", + [ + analytics_admin.UpdateReportingIdentitySettingsRequest, + dict, + ], +) +def test_update_reporting_identity_settings_rest_call_success(request_type): + client = AnalyticsAdminServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + # send a request that will satisfy transcoding + request_init = { + "reporting_identity_settings": { + "name": "properties/sample1/reportingIdentitySettings" + } + } + request_init["reporting_identity_settings"] = { + "name": "properties/sample1/reportingIdentitySettings", + "reporting_identity": 1, + } + # 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 = analytics_admin.UpdateReportingIdentitySettingsRequest.meta.fields[ + "reporting_identity_settings" + ] + + 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[ + "reporting_identity_settings" + ].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["reporting_identity_settings"][field]) + ): + del request_init["reporting_identity_settings"][field][i][subfield] + else: + del request_init["reporting_identity_settings"][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 = resources.ReportingIdentitySettings( + name="name_value", + reporting_identity=resources.ReportingIdentitySettings.ReportingIdentity.BLENDED, + ) + + # Wrap the value into a proper Response obj + response_value = mock.Mock() + response_value.status_code = 200 + + # Convert return value to protobuf type + return_value = resources.ReportingIdentitySettings.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 + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + response = client.update_reporting_identity_settings(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, resources.ReportingIdentitySettings) + assert response.name == "name_value" + assert ( + response.reporting_identity + == resources.ReportingIdentitySettings.ReportingIdentity.BLENDED + ) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_update_reporting_identity_settings_rest_interceptors(null_interceptor): + transport = transports.AnalyticsAdminServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.AnalyticsAdminServiceRestInterceptor(), + ) + client = AnalyticsAdminServiceClient(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.AnalyticsAdminServiceRestInterceptor, + "post_update_reporting_identity_settings", + ) as post, + mock.patch.object( + transports.AnalyticsAdminServiceRestInterceptor, + "post_update_reporting_identity_settings_with_metadata", + ) as post_with_metadata, + mock.patch.object( + transports.AnalyticsAdminServiceRestInterceptor, + "pre_update_reporting_identity_settings", + ) as pre, + ): + pre.assert_not_called() + post.assert_not_called() + post_with_metadata.assert_not_called() + pb_message = analytics_admin.UpdateReportingIdentitySettingsRequest.pb( + analytics_admin.UpdateReportingIdentitySettingsRequest() + ) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = mock.Mock() + req.return_value.status_code = 200 + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + return_value = resources.ReportingIdentitySettings.to_json( + resources.ReportingIdentitySettings() + ) + req.return_value.content = return_value + + request = analytics_admin.UpdateReportingIdentitySettingsRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = resources.ReportingIdentitySettings() + post_with_metadata.return_value = ( + resources.ReportingIdentitySettings(), + metadata, + ) + + client.update_reporting_identity_settings( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + post_with_metadata.assert_called_once() + + def test_get_user_provided_data_settings_rest_bad_request( request_type=analytics_admin.GetUserProvidedDataSettingsRequest, ): @@ -126995,6 +127840,27 @@ def test_get_reporting_identity_settings_empty_call_rest(): assert args[0] == request_msg +# This test is a coverage failsafe to make sure that totally empty calls, +# i.e. request == None and no flattened fields passed, work. +def test_update_reporting_identity_settings_empty_call_rest(): + client = AnalyticsAdminServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the actual call, and fake the request. + with mock.patch.object( + type(client.transport.update_reporting_identity_settings), "__call__" + ) as call: + client.update_reporting_identity_settings(request=None) + + # Establish that the underlying stub method was called. + call.assert_called() + _, args, _ = call.mock_calls[0] + request_msg = analytics_admin.UpdateReportingIdentitySettingsRequest() + assert args[0] == request_msg + + # This test is a coverage failsafe to make sure that totally empty calls, # i.e. request == None and no flattened fields passed, work. def test_get_user_provided_data_settings_empty_call_rest(): @@ -127203,6 +128069,7 @@ def test_analytics_admin_service_base_transport(): "update_subproperty_sync_config", "get_subproperty_sync_config", "get_reporting_identity_settings", + "update_reporting_identity_settings", "get_user_provided_data_settings", ) for method in methods: @@ -127975,6 +128842,9 @@ def test_analytics_admin_service_client_transport_session_collision(transport_na session1 = client1.transport.get_reporting_identity_settings._session session2 = client2.transport.get_reporting_identity_settings._session assert session1 != session2 + session1 = client1.transport.update_reporting_identity_settings._session + session2 = client2.transport.update_reporting_identity_settings._session + assert session1 != session2 session1 = client1.transport.get_user_provided_data_settings._session session2 = client2.transport.get_user_provided_data_settings._session assert session1 != session2 diff --git a/packages/google-apps-chat/google/apps/chat_v1/types/message.py b/packages/google-apps-chat/google/apps/chat_v1/types/message.py index d85925d9b891..cb3cf60c0bf7 100644 --- a/packages/google-apps-chat/google/apps/chat_v1/types/message.py +++ b/packages/google-apps-chat/google/apps/chat_v1/types/message.py @@ -417,10 +417,6 @@ class AttachedGif(proto.Message): class QuotedMessageMetadata(proto.Message): r"""Information about a message that another message quotes. - When you create a message, you can quote messages within the same - thread, or quote a root message to create a new root message. - However, you can't quote a message reply from a different thread. - When you update a message, you can't add or replace the ``quotedMessageMetadata`` field, but you can remove it. @@ -462,19 +458,24 @@ class QuoteType(proto.Enum): QUOTE_TYPE_UNSPECIFIED (0): Reserved. This value is unused. REPLY (1): - If quote_type is ``REPLY``, you can do the following: + When ``quote_type`` is ``REPLY``, you can do the following: - If you're replying in a thread, you can quote another message in that thread. - If you're creating a root message, you can quote another root message in that space. + FORWARD (2): + When ``quote_type`` is ``FORWARD``, you can quote a: + + - Message from a different space. - You can't quote a message reply from a different thread. + - Message reply from a different thread in the same space. """ QUOTE_TYPE_UNSPECIFIED = 0 REPLY = 1 + FORWARD = 2 name: str = proto.Field( proto.STRING, diff --git a/packages/google-cloud-build/google/cloud/devtools/cloudbuild_v1/types/cloudbuild.py b/packages/google-cloud-build/google/cloud/devtools/cloudbuild_v1/types/cloudbuild.py index d662fee0ff8e..4b699b419808 100644 --- a/packages/google-cloud-build/google/cloud/devtools/cloudbuild_v1/types/cloudbuild.py +++ b/packages/google-cloud-build/google/cloud/devtools/cloudbuild_v1/types/cloudbuild.py @@ -3684,6 +3684,8 @@ class MachineType(proto.Enum): Highcpu e2 machine with 32 CPUs. E2_MEDIUM (7): E2 machine with 1 CPU. + E2_STANDARD_2 (11): + E2 machine with 2 CPUs. """ UNSPECIFIED = 0 @@ -3692,6 +3694,7 @@ class MachineType(proto.Enum): E2_HIGHCPU_8 = 5 E2_HIGHCPU_32 = 6 E2_MEDIUM = 7 + E2_STANDARD_2 = 11 class SubstitutionOption(proto.Enum): r"""Specifies the behavior when there is an error in the diff --git a/packages/google-cloud-ces/google/cloud/ces_v1beta/types/agent_tool.py b/packages/google-cloud-ces/google/cloud/ces_v1beta/types/agent_tool.py index 762037cf0381..c5efc6f507ad 100644 --- a/packages/google-cloud-ces/google/cloud/ces_v1beta/types/agent_tool.py +++ b/packages/google-cloud-ces/google/cloud/ces_v1beta/types/agent_tool.py @@ -36,11 +36,6 @@ class AgentTool(proto.Message): Required. The name of the agent tool. description (str): Optional. Description of the tool's purpose. - root_agent (str): - Optional. Deprecated: Use ``agent`` instead. The resource - name of the root agent that is the entry point of the tool. - Format: - ``projects/{project}/locations/{location}/agents/{agent}`` agent (str): Optional. The resource name of the agent that is the entry point of the tool. Format: @@ -55,10 +50,6 @@ class AgentTool(proto.Message): proto.STRING, number=2, ) - root_agent: str = proto.Field( - proto.STRING, - number=3, - ) agent: str = proto.Field( proto.STRING, number=4, diff --git a/packages/google-cloud-ces/tests/unit/gapic/ces_v1beta/test_agent_service.py b/packages/google-cloud-ces/tests/unit/gapic/ces_v1beta/test_agent_service.py index 8c34161fe618..501b21ad1dbf 100644 --- a/packages/google-cloud-ces/tests/unit/gapic/ces_v1beta/test_agent_service.py +++ b/packages/google-cloud-ces/tests/unit/gapic/ces_v1beta/test_agent_service.py @@ -38341,7 +38341,6 @@ def test_create_tool_rest_call_success(request_type): "agent_tool": { "name": "name_value", "description": "description_value", - "root_agent": "root_agent_value", "agent": "agent_value", }, "widget_tool": { @@ -38817,7 +38816,6 @@ def test_update_tool_rest_call_success(request_type): "agent_tool": { "name": "name_value", "description": "description_value", - "root_agent": "root_agent_value", "agent": "agent_value", }, "widget_tool": { @@ -42782,7 +42780,6 @@ def test_create_app_version_rest_call_success(request_type): "agent_tool": { "name": "name_value", "description": "description_value", - "root_agent": "root_agent_value", "agent": "agent_value", }, "widget_tool": { diff --git a/packages/google-cloud-chronicle/docs/chronicle_v1/rule_execution_error_service.rst b/packages/google-cloud-chronicle/docs/chronicle_v1/rule_execution_error_service.rst new file mode 100644 index 000000000000..e95d79bd0784 --- /dev/null +++ b/packages/google-cloud-chronicle/docs/chronicle_v1/rule_execution_error_service.rst @@ -0,0 +1,10 @@ +RuleExecutionErrorService +------------------------------------------- + +.. automodule:: google.cloud.chronicle_v1.services.rule_execution_error_service + :members: + :inherited-members: + +.. automodule:: google.cloud.chronicle_v1.services.rule_execution_error_service.pagers + :members: + :inherited-members: diff --git a/packages/google-cloud-chronicle/docs/chronicle_v1/services_.rst b/packages/google-cloud-chronicle/docs/chronicle_v1/services_.rst index e0ae32d4d4f2..1cde737362f4 100644 --- a/packages/google-cloud-chronicle/docs/chronicle_v1/services_.rst +++ b/packages/google-cloud-chronicle/docs/chronicle_v1/services_.rst @@ -13,4 +13,5 @@ Services for Google Cloud Chronicle v1 API instance_service native_dashboard_service reference_list_service + rule_execution_error_service rule_service diff --git a/packages/google-cloud-chronicle/google/cloud/chronicle/__init__.py b/packages/google-cloud-chronicle/google/cloud/chronicle/__init__.py index 35c56ef21f6d..8be7d23a51d0 100644 --- a/packages/google-cloud-chronicle/google/cloud/chronicle/__init__.py +++ b/packages/google-cloud-chronicle/google/cloud/chronicle/__init__.py @@ -76,6 +76,12 @@ from google.cloud.chronicle_v1.services.reference_list_service.client import ( ReferenceListServiceClient, ) +from google.cloud.chronicle_v1.services.rule_execution_error_service.async_client import ( + RuleExecutionErrorServiceAsyncClient, +) +from google.cloud.chronicle_v1.services.rule_execution_error_service.client import ( + RuleExecutionErrorServiceClient, +) from google.cloud.chronicle_v1.services.rule_service.async_client import ( RuleServiceAsyncClient, ) @@ -235,11 +241,14 @@ ListReferenceListsResponse, ReferenceList, ReferenceListEntry, + ReferenceListError, ReferenceListScope, ReferenceListSyntaxType, ReferenceListView, ScopeInfo, UpdateReferenceListRequest, + VerifyReferenceListRequest, + VerifyReferenceListResponse, ) from google.cloud.chronicle_v1.types.rule import ( CompilationDiagnostic, @@ -269,6 +278,13 @@ Severity, UpdateRuleDeploymentRequest, UpdateRuleRequest, + VerifyRuleTextRequest, + VerifyRuleTextResponse, +) +from google.cloud.chronicle_v1.types.rule_execution_error import ( + ListRuleExecutionErrorsRequest, + ListRuleExecutionErrorsResponse, + RuleExecutionError, ) __all__ = ( @@ -292,6 +308,8 @@ "NativeDashboardServiceAsyncClient", "ReferenceListServiceClient", "ReferenceListServiceAsyncClient", + "RuleExecutionErrorServiceClient", + "RuleExecutionErrorServiceAsyncClient", "RuleServiceClient", "RuleServiceAsyncClient", "BigQueryExport", @@ -431,9 +449,12 @@ "ListReferenceListsResponse", "ReferenceList", "ReferenceListEntry", + "ReferenceListError", "ReferenceListScope", "ScopeInfo", "UpdateReferenceListRequest", + "VerifyReferenceListRequest", + "VerifyReferenceListResponse", "ReferenceListSyntaxType", "ReferenceListView", "CompilationDiagnostic", @@ -460,7 +481,12 @@ "Severity", "UpdateRuleDeploymentRequest", "UpdateRuleRequest", + "VerifyRuleTextRequest", + "VerifyRuleTextResponse", "RuleType", "RuleView", "RunFrequency", + "ListRuleExecutionErrorsRequest", + "ListRuleExecutionErrorsResponse", + "RuleExecutionError", ) diff --git a/packages/google-cloud-chronicle/google/cloud/chronicle_v1/__init__.py b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/__init__.py index 8f93142f2184..3f77c05f421f 100644 --- a/packages/google-cloud-chronicle/google/cloud/chronicle_v1/__init__.py +++ b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/__init__.py @@ -57,6 +57,10 @@ ReferenceListServiceAsyncClient, ReferenceListServiceClient, ) +from .services.rule_execution_error_service import ( + RuleExecutionErrorServiceAsyncClient, + RuleExecutionErrorServiceClient, +) from .services.rule_service import RuleServiceAsyncClient, RuleServiceClient from .types.big_query_export import ( BigQueryExport, @@ -211,11 +215,14 @@ ListReferenceListsResponse, ReferenceList, ReferenceListEntry, + ReferenceListError, ReferenceListScope, ReferenceListSyntaxType, ReferenceListView, ScopeInfo, UpdateReferenceListRequest, + VerifyReferenceListRequest, + VerifyReferenceListResponse, ) from .types.rule import ( CompilationDiagnostic, @@ -245,6 +252,13 @@ Severity, UpdateRuleDeploymentRequest, UpdateRuleRequest, + VerifyRuleTextRequest, + VerifyRuleTextResponse, +) +from .types.rule_execution_error import ( + ListRuleExecutionErrorsRequest, + ListRuleExecutionErrorsResponse, + RuleExecutionError, ) if hasattr(api_core, "check_python_version") and hasattr( @@ -341,6 +355,7 @@ def _get_version(dependency_name): "InstanceServiceAsyncClient", "NativeDashboardServiceAsyncClient", "ReferenceListServiceAsyncClient", + "RuleExecutionErrorServiceAsyncClient", "RuleServiceAsyncClient", "AddChartRequest", "AddChartResponse", @@ -467,6 +482,8 @@ def _get_version(dependency_name): "ListRetrohuntsResponse", "ListRuleDeploymentsRequest", "ListRuleDeploymentsResponse", + "ListRuleExecutionErrorsRequest", + "ListRuleExecutionErrorsResponse", "ListRuleRevisionsRequest", "ListRuleRevisionsResponse", "ListRulesRequest", @@ -487,6 +504,7 @@ def _get_version(dependency_name): "QueryRuntimeError", "ReferenceList", "ReferenceListEntry", + "ReferenceListError", "ReferenceListScope", "ReferenceListServiceClient", "ReferenceListSyntaxType", @@ -497,6 +515,8 @@ def _get_version(dependency_name): "RetrohuntMetadata", "Rule", "RuleDeployment", + "RuleExecutionError", + "RuleExecutionErrorServiceClient", "RuleServiceClient", "RuleType", "RuleView", @@ -519,6 +539,10 @@ def _get_version(dependency_name): "UpdateRuleDeploymentRequest", "UpdateRuleRequest", "UpdateWatchlistRequest", + "VerifyReferenceListRequest", + "VerifyReferenceListResponse", + "VerifyRuleTextRequest", + "VerifyRuleTextResponse", "VisualMapType", "Watchlist", "WatchlistUserPreferences", diff --git a/packages/google-cloud-chronicle/google/cloud/chronicle_v1/gapic_metadata.json b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/gapic_metadata.json index b5400b21a874..511d879a4faa 100644 --- a/packages/google-cloud-chronicle/google/cloud/chronicle_v1/gapic_metadata.json +++ b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/gapic_metadata.json @@ -995,6 +995,11 @@ "methods": [ "update_reference_list" ] + }, + "VerifyReferenceList": { + "methods": [ + "verify_reference_list" + ] } } }, @@ -1020,6 +1025,11 @@ "methods": [ "update_reference_list" ] + }, + "VerifyReferenceList": { + "methods": [ + "verify_reference_list" + ] } } }, @@ -1045,6 +1055,45 @@ "methods": [ "update_reference_list" ] + }, + "VerifyReferenceList": { + "methods": [ + "verify_reference_list" + ] + } + } + } + } + }, + "RuleExecutionErrorService": { + "clients": { + "grpc": { + "libraryClient": "RuleExecutionErrorServiceClient", + "rpcs": { + "ListRuleExecutionErrors": { + "methods": [ + "list_rule_execution_errors" + ] + } + } + }, + "grpc-async": { + "libraryClient": "RuleExecutionErrorServiceAsyncClient", + "rpcs": { + "ListRuleExecutionErrors": { + "methods": [ + "list_rule_execution_errors" + ] + } + } + }, + "rest": { + "libraryClient": "RuleExecutionErrorServiceClient", + "rpcs": { + "ListRuleExecutionErrors": { + "methods": [ + "list_rule_execution_errors" + ] } } } @@ -1114,6 +1163,11 @@ "methods": [ "update_rule_deployment" ] + }, + "VerifyRuleText": { + "methods": [ + "verify_rule_text" + ] } } }, @@ -1179,6 +1233,11 @@ "methods": [ "update_rule_deployment" ] + }, + "VerifyRuleText": { + "methods": [ + "verify_rule_text" + ] } } }, @@ -1244,6 +1303,11 @@ "methods": [ "update_rule_deployment" ] + }, + "VerifyRuleText": { + "methods": [ + "verify_rule_text" + ] } } } diff --git a/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/reference_list_service/async_client.py b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/reference_list_service/async_client.py index 43e1bcda8eee..931452f93c3f 100644 --- a/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/reference_list_service/async_client.py +++ b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/reference_list_service/async_client.py @@ -80,6 +80,8 @@ class ReferenceListServiceAsyncClient: _DEFAULT_ENDPOINT_TEMPLATE = ReferenceListServiceClient._DEFAULT_ENDPOINT_TEMPLATE _DEFAULT_UNIVERSE = ReferenceListServiceClient._DEFAULT_UNIVERSE + instance_path = staticmethod(ReferenceListServiceClient.instance_path) + parse_instance_path = staticmethod(ReferenceListServiceClient.parse_instance_path) reference_list_path = staticmethod(ReferenceListServiceClient.reference_list_path) parse_reference_list_path = staticmethod( ReferenceListServiceClient.parse_reference_list_path @@ -835,6 +837,97 @@ async def sample_update_reference_list(): # Done; return the response. return response + async def verify_reference_list( + self, + request: Optional[ + Union[reference_list.VerifyReferenceListRequest, dict] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> reference_list.VerifyReferenceListResponse: + r"""VerifyReferenceList validates list content and + returns line errors, if any. + + .. 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 chronicle_v1 + + async def sample_verify_reference_list(): + # Create a client + client = chronicle_v1.ReferenceListServiceAsyncClient() + + # Initialize request argument(s) + entries = chronicle_v1.ReferenceListEntry() + entries.value = "value_value" + + request = chronicle_v1.VerifyReferenceListRequest( + instance="instance_value", + syntax_type="REFERENCE_LIST_SYNTAX_TYPE_CIDR", + entries=entries, + ) + + # Make the request + response = await client.verify_reference_list(request=request) + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.chronicle_v1.types.VerifyReferenceListRequest, dict]]): + The request object. VerifyReferenceList request message. + 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + google.cloud.chronicle_v1.types.VerifyReferenceListResponse: + VerifyListResponse response message. + """ + # Create or coerce a protobuf request object. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, reference_list.VerifyReferenceListRequest): + request = reference_list.VerifyReferenceListRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.verify_reference_list + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("instance", request.instance),)), + ) + + # 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[Union[operations_pb2.ListOperationsRequest, dict]] = None, diff --git a/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/reference_list_service/client.py b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/reference_list_service/client.py index d7ad5e67e3ab..50f3d80bfecf 100644 --- a/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/reference_list_service/client.py +++ b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/reference_list_service/client.py @@ -233,6 +233,28 @@ def transport(self) -> ReferenceListServiceTransport: """ return self._transport + @staticmethod + def instance_path( + project: str, + location: str, + instance: str, + ) -> str: + """Returns a fully-qualified instance string.""" + return "projects/{project}/locations/{location}/instances/{instance}".format( + project=project, + location=location, + instance=instance, + ) + + @staticmethod + def parse_instance_path(path: str) -> Dict[str, str]: + """Parses a instance path into its component segments.""" + m = re.match( + r"^projects/(?P.+?)/locations/(?P.+?)/instances/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + @staticmethod def reference_list_path( project: str, @@ -1256,6 +1278,95 @@ def sample_update_reference_list(): # Done; return the response. return response + def verify_reference_list( + self, + request: Optional[ + Union[reference_list.VerifyReferenceListRequest, dict] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> reference_list.VerifyReferenceListResponse: + r"""VerifyReferenceList validates list content and + returns line errors, if any. + + .. 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 chronicle_v1 + + def sample_verify_reference_list(): + # Create a client + client = chronicle_v1.ReferenceListServiceClient() + + # Initialize request argument(s) + entries = chronicle_v1.ReferenceListEntry() + entries.value = "value_value" + + request = chronicle_v1.VerifyReferenceListRequest( + instance="instance_value", + syntax_type="REFERENCE_LIST_SYNTAX_TYPE_CIDR", + entries=entries, + ) + + # Make the request + response = client.verify_reference_list(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.chronicle_v1.types.VerifyReferenceListRequest, dict]): + The request object. VerifyReferenceList request message. + 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + google.cloud.chronicle_v1.types.VerifyReferenceListResponse: + VerifyListResponse response message. + """ + # Create or coerce a protobuf request object. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, reference_list.VerifyReferenceListRequest): + request = reference_list.VerifyReferenceListRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.verify_reference_list] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("instance", request.instance),)), + ) + + # 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) -> "ReferenceListServiceClient": return self diff --git a/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/reference_list_service/transports/base.py b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/reference_list_service/transports/base.py index 5a54cf899042..db80f452fae1 100644 --- a/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/reference_list_service/transports/base.py +++ b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/reference_list_service/transports/base.py @@ -41,7 +41,11 @@ class ReferenceListServiceTransport(abc.ABC): """Abstract transport class for ReferenceListService.""" - AUTH_SCOPES = ("https://www.googleapis.com/auth/cloud-platform",) + AUTH_SCOPES = ( + "https://www.googleapis.com/auth/chronicle", + "https://www.googleapis.com/auth/chronicle.readonly", + "https://www.googleapis.com/auth/cloud-platform", + ) DEFAULT_HOST: str = "chronicle.googleapis.com" @@ -182,6 +186,20 @@ def _prep_wrapped_messages(self, client_info): default_timeout=60.0, client_info=client_info, ), + self.verify_reference_list: gapic_v1.method.wrap_method( + self.verify_reference_list, + default_retry=retries.Retry( + initial=1.0, + maximum=60.0, + multiplier=1.3, + predicate=retries.if_exception_type( + core_exceptions.ServiceUnavailable, + ), + deadline=60.0, + ), + default_timeout=60.0, + client_info=client_info, + ), self.cancel_operation: gapic_v1.method.wrap_method( self.cancel_operation, default_timeout=None, @@ -258,6 +276,18 @@ def update_reference_list( ]: raise NotImplementedError() + @property + def verify_reference_list( + self, + ) -> Callable[ + [reference_list.VerifyReferenceListRequest], + Union[ + reference_list.VerifyReferenceListResponse, + Awaitable[reference_list.VerifyReferenceListResponse], + ], + ]: + raise NotImplementedError() + @property def list_operations( self, diff --git a/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/reference_list_service/transports/grpc.py b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/reference_list_service/transports/grpc.py index afb29f951599..02290a95738a 100644 --- a/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/reference_list_service/transports/grpc.py +++ b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/reference_list_service/transports/grpc.py @@ -443,6 +443,36 @@ def update_reference_list( ) return self._stubs["update_reference_list"] + @property + def verify_reference_list( + self, + ) -> Callable[ + [reference_list.VerifyReferenceListRequest], + reference_list.VerifyReferenceListResponse, + ]: + r"""Return a callable for the verify reference list method over gRPC. + + VerifyReferenceList validates list content and + returns line errors, if any. + + Returns: + Callable[[~.VerifyReferenceListRequest], + ~.VerifyReferenceListResponse]: + 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 "verify_reference_list" not in self._stubs: + self._stubs["verify_reference_list"] = self._logged_channel.unary_unary( + "/google.cloud.chronicle.v1.ReferenceListService/VerifyReferenceList", + request_serializer=reference_list.VerifyReferenceListRequest.serialize, + response_deserializer=reference_list.VerifyReferenceListResponse.deserialize, + ) + return self._stubs["verify_reference_list"] + def close(self): self._logged_channel.close() diff --git a/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/reference_list_service/transports/grpc_asyncio.py b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/reference_list_service/transports/grpc_asyncio.py index 185593e53a91..81b94111dcfd 100644 --- a/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/reference_list_service/transports/grpc_asyncio.py +++ b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/reference_list_service/transports/grpc_asyncio.py @@ -452,6 +452,36 @@ def update_reference_list( ) return self._stubs["update_reference_list"] + @property + def verify_reference_list( + self, + ) -> Callable[ + [reference_list.VerifyReferenceListRequest], + Awaitable[reference_list.VerifyReferenceListResponse], + ]: + r"""Return a callable for the verify reference list method over gRPC. + + VerifyReferenceList validates list content and + returns line errors, if any. + + Returns: + Callable[[~.VerifyReferenceListRequest], + Awaitable[~.VerifyReferenceListResponse]]: + 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 "verify_reference_list" not in self._stubs: + self._stubs["verify_reference_list"] = self._logged_channel.unary_unary( + "/google.cloud.chronicle.v1.ReferenceListService/VerifyReferenceList", + request_serializer=reference_list.VerifyReferenceListRequest.serialize, + response_deserializer=reference_list.VerifyReferenceListResponse.deserialize, + ) + return self._stubs["verify_reference_list"] + def _prep_wrapped_messages(self, client_info): """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" self._wrapped_methods = { @@ -493,6 +523,20 @@ def _prep_wrapped_messages(self, client_info): default_timeout=60.0, client_info=client_info, ), + self.verify_reference_list: self._wrap_method( + self.verify_reference_list, + default_retry=retries.AsyncRetry( + initial=1.0, + maximum=60.0, + multiplier=1.3, + predicate=retries.if_exception_type( + core_exceptions.ServiceUnavailable, + ), + deadline=60.0, + ), + default_timeout=60.0, + client_info=client_info, + ), self.cancel_operation: self._wrap_method( self.cancel_operation, default_timeout=None, diff --git a/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/reference_list_service/transports/rest.py b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/reference_list_service/transports/rest.py index de4f4cef98f1..edf00c108178 100644 --- a/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/reference_list_service/transports/rest.py +++ b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/reference_list_service/transports/rest.py @@ -106,6 +106,14 @@ def post_update_reference_list(self, response): logging.log(f"Received response: {response}") return response + def pre_verify_reference_list(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_verify_reference_list(self, response): + logging.log(f"Received response: {response}") + return response + transport = ReferenceListServiceRestTransport(interceptor=MyCustomReferenceListServiceInterceptor()) client = ReferenceListServiceClient(transport=transport) @@ -314,6 +322,58 @@ def post_update_reference_list_with_metadata( """ return response, metadata + def pre_verify_reference_list( + self, + request: reference_list.VerifyReferenceListRequest, + metadata: Sequence[Tuple[str, Union[str, bytes]]], + ) -> Tuple[ + reference_list.VerifyReferenceListRequest, + Sequence[Tuple[str, Union[str, bytes]]], + ]: + """Pre-rpc interceptor for verify_reference_list + + Override in a subclass to manipulate the request or metadata + before they are sent to the ReferenceListService server. + """ + return request, metadata + + def post_verify_reference_list( + self, response: reference_list.VerifyReferenceListResponse + ) -> reference_list.VerifyReferenceListResponse: + """Post-rpc interceptor for verify_reference_list + + DEPRECATED. Please use the `post_verify_reference_list_with_metadata` + interceptor instead. + + Override in a subclass to read or manipulate the response + after it is returned by the ReferenceListService server but before + it is returned to user code. This `post_verify_reference_list` interceptor runs + before the `post_verify_reference_list_with_metadata` interceptor. + """ + return response + + def post_verify_reference_list_with_metadata( + self, + response: reference_list.VerifyReferenceListResponse, + metadata: Sequence[Tuple[str, Union[str, bytes]]], + ) -> Tuple[ + reference_list.VerifyReferenceListResponse, + Sequence[Tuple[str, Union[str, bytes]]], + ]: + """Post-rpc interceptor for verify_reference_list + + Override in a subclass to read or manipulate the response or metadata after it + is returned by the ReferenceListService server but before it is returned to user code. + + We recommend only using this `post_verify_reference_list_with_metadata` + interceptor in new development instead of the `post_verify_reference_list` interceptor. + When both interceptors are used, this `post_verify_reference_list_with_metadata` interceptor runs after the + `post_verify_reference_list` interceptor. The (possibly modified) response returned by + `post_verify_reference_list` will be passed to + `post_verify_reference_list_with_metadata`. + """ + return response, metadata + def pre_cancel_operation( self, request: operations_pb2.CancelOperationRequest, @@ -1127,6 +1187,161 @@ def __call__( ) return resp + class _VerifyReferenceList( + _BaseReferenceListServiceRestTransport._BaseVerifyReferenceList, + ReferenceListServiceRestStub, + ): + def __hash__(self): + return hash("ReferenceListServiceRestTransport.VerifyReferenceList") + + @staticmethod + def _get_response( + host, + metadata, + query_params, + session, + timeout, + transcoded_request, + body=None, + ): + uri = transcoded_request["uri"] + method = transcoded_request["method"] + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(session, method)( + "{host}{uri}".format(host=host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + data=body, + ) + return response + + def __call__( + self, + request: reference_list.VerifyReferenceListRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> reference_list.VerifyReferenceListResponse: + r"""Call the verify reference list method over HTTP. + + Args: + request (~.reference_list.VerifyReferenceListRequest): + The request object. VerifyReferenceList request message. + 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + ~.reference_list.VerifyReferenceListResponse: + VerifyListResponse response message. + """ + + http_options = _BaseReferenceListServiceRestTransport._BaseVerifyReferenceList._get_http_options() + + request, metadata = self._interceptor.pre_verify_reference_list( + request, metadata + ) + transcoded_request = _BaseReferenceListServiceRestTransport._BaseVerifyReferenceList._get_transcoded_request( + http_options, request + ) + + body = _BaseReferenceListServiceRestTransport._BaseVerifyReferenceList._get_request_body_json( + transcoded_request + ) + + # Jsonify the query params + query_params = _BaseReferenceListServiceRestTransport._BaseVerifyReferenceList._get_query_params_json( + transcoded_request + ) + + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + logging.DEBUG + ): # pragma: NO COVER + request_url = "{host}{uri}".format( + host=self._host, uri=transcoded_request["uri"] + ) + method = transcoded_request["method"] + try: + request_payload = type(request).to_json(request) + except: + request_payload = None + http_request = { + "payload": request_payload, + "requestMethod": method, + "requestUrl": request_url, + "headers": dict(metadata), + } + _LOGGER.debug( + f"Sending request for google.cloud.chronicle_v1.ReferenceListServiceClient.VerifyReferenceList", + extra={ + "serviceName": "google.cloud.chronicle.v1.ReferenceListService", + "rpcName": "VerifyReferenceList", + "httpRequest": http_request, + "metadata": http_request["headers"], + }, + ) + + # Send the request + response = ( + ReferenceListServiceRestTransport._VerifyReferenceList._get_response( + self._host, + metadata, + query_params, + self._session, + timeout, + transcoded_request, + 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 = reference_list.VerifyReferenceListResponse() + pb_resp = reference_list.VerifyReferenceListResponse.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + + resp = self._interceptor.post_verify_reference_list(resp) + response_metadata = [(k, str(v)) for k, v in response.headers.items()] + resp, _ = self._interceptor.post_verify_reference_list_with_metadata( + resp, response_metadata + ) + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + logging.DEBUG + ): # pragma: NO COVER + try: + response_payload = ( + reference_list.VerifyReferenceListResponse.to_json(response) + ) + except: + response_payload = None + http_response = { + "payload": response_payload, + "headers": dict(response.headers), + "status": response.status_code, + } + _LOGGER.debug( + "Received response for google.cloud.chronicle_v1.ReferenceListServiceClient.verify_reference_list", + extra={ + "serviceName": "google.cloud.chronicle.v1.ReferenceListService", + "rpcName": "VerifyReferenceList", + "metadata": http_response["headers"], + "httpResponse": http_response, + }, + ) + return resp + @property def create_reference_list( self, @@ -1170,6 +1385,17 @@ def update_reference_list( # In C++ this would require a dynamic_cast return self._UpdateReferenceList(self._session, self._host, self._interceptor) # type: ignore + @property + def verify_reference_list( + self, + ) -> Callable[ + [reference_list.VerifyReferenceListRequest], + reference_list.VerifyReferenceListResponse, + ]: + # 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._VerifyReferenceList(self._session, self._host, self._interceptor) # type: ignore + @property def cancel_operation(self): return self._CancelOperation(self._session, self._host, self._interceptor) # type: ignore diff --git a/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/reference_list_service/transports/rest_base.py b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/reference_list_service/transports/rest_base.py index 3a964df8c43b..c1d673052a92 100644 --- a/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/reference_list_service/transports/rest_base.py +++ b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/reference_list_service/transports/rest_base.py @@ -299,6 +299,63 @@ def _get_query_params_json(transcoded_request): query_params["$alt"] = "json;enum-encoding=int" return query_params + class _BaseVerifyReferenceList: + def __hash__(self): # pragma: NO COVER + return NotImplementedError("__hash__ must be implemented.") + + __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 + } + + @staticmethod + def _get_http_options(): + http_options: List[Dict[str, str]] = [ + { + "method": "post", + "uri": "/v1/{instance=projects/*/locations/*/instances/*}:verifyReferenceList", + "body": "*", + }, + ] + return http_options + + @staticmethod + def _get_transcoded_request(http_options, request): + pb_request = reference_list.VerifyReferenceListRequest.pb(request) + transcoded_request = path_template.transcode(http_options, pb_request) + return transcoded_request + + @staticmethod + def _get_request_body_json(transcoded_request): + # Jsonify the request body + + body = json_format.MessageToJson( + transcoded_request["body"], use_integers_for_enums=True + ) + return body + + @staticmethod + def _get_query_params_json(transcoded_request): + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + use_integers_for_enums=True, + ) + ) + query_params.update( + _BaseReferenceListServiceRestTransport._BaseVerifyReferenceList._get_unset_required_fields( + query_params + ) + ) + + query_params["$alt"] = "json;enum-encoding=int" + return query_params + class _BaseCancelOperation: def __hash__(self): # pragma: NO COVER return NotImplementedError("__hash__ must be implemented.") diff --git a/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_execution_error_service/__init__.py b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_execution_error_service/__init__.py new file mode 100644 index 000000000000..19e2479d30d5 --- /dev/null +++ b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_execution_error_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2026 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 RuleExecutionErrorServiceAsyncClient +from .client import RuleExecutionErrorServiceClient + +__all__ = ( + "RuleExecutionErrorServiceClient", + "RuleExecutionErrorServiceAsyncClient", +) diff --git a/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_execution_error_service/async_client.py b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_execution_error_service/async_client.py new file mode 100644 index 000000000000..ac0db34ff1f4 --- /dev/null +++ b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_execution_error_service/async_client.py @@ -0,0 +1,708 @@ +# -*- coding: utf-8 -*- +# Copyright 2026 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 logging as std_logging +import re +from collections import OrderedDict +from typing import ( + Callable, + Dict, + Mapping, + MutableMapping, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, +) + +import google.protobuf +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.chronicle_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.longrunning import operations_pb2 # type: ignore + +from google.cloud.chronicle_v1.services.rule_execution_error_service import pagers +from google.cloud.chronicle_v1.types import rule_execution_error + +from .client import RuleExecutionErrorServiceClient +from .transports.base import DEFAULT_CLIENT_INFO, RuleExecutionErrorServiceTransport +from .transports.grpc_asyncio import RuleExecutionErrorServiceGrpcAsyncIOTransport + +try: + from google.api_core import client_logging # type: ignore + + CLIENT_LOGGING_SUPPORTED = True # pragma: NO COVER +except ImportError: # pragma: NO COVER + CLIENT_LOGGING_SUPPORTED = False + +_LOGGER = std_logging.getLogger(__name__) + + +class RuleExecutionErrorServiceAsyncClient: + """RuleExecutionErrorService contains endpoints related to rule + execution errors. + """ + + _client: RuleExecutionErrorServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = RuleExecutionErrorServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = RuleExecutionErrorServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = ( + RuleExecutionErrorServiceClient._DEFAULT_ENDPOINT_TEMPLATE + ) + _DEFAULT_UNIVERSE = RuleExecutionErrorServiceClient._DEFAULT_UNIVERSE + + curated_rule_path = staticmethod(RuleExecutionErrorServiceClient.curated_rule_path) + parse_curated_rule_path = staticmethod( + RuleExecutionErrorServiceClient.parse_curated_rule_path + ) + rule_path = staticmethod(RuleExecutionErrorServiceClient.rule_path) + parse_rule_path = staticmethod(RuleExecutionErrorServiceClient.parse_rule_path) + rule_execution_error_path = staticmethod( + RuleExecutionErrorServiceClient.rule_execution_error_path + ) + parse_rule_execution_error_path = staticmethod( + RuleExecutionErrorServiceClient.parse_rule_execution_error_path + ) + common_billing_account_path = staticmethod( + RuleExecutionErrorServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + RuleExecutionErrorServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod( + RuleExecutionErrorServiceClient.common_folder_path + ) + parse_common_folder_path = staticmethod( + RuleExecutionErrorServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + RuleExecutionErrorServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + RuleExecutionErrorServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod( + RuleExecutionErrorServiceClient.common_project_path + ) + parse_common_project_path = staticmethod( + RuleExecutionErrorServiceClient.parse_common_project_path + ) + common_location_path = staticmethod( + RuleExecutionErrorServiceClient.common_location_path + ) + parse_common_location_path = staticmethod( + RuleExecutionErrorServiceClient.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: + RuleExecutionErrorServiceAsyncClient: The constructed client. + """ + sa_info_func = ( + RuleExecutionErrorServiceClient.from_service_account_info.__func__ # type: ignore + ) + return sa_info_func(RuleExecutionErrorServiceAsyncClient, info, *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: + RuleExecutionErrorServiceAsyncClient: The constructed client. + """ + sa_file_func = ( + RuleExecutionErrorServiceClient.from_service_account_file.__func__ # type: ignore + ) + return sa_file_func( + RuleExecutionErrorServiceAsyncClient, filename, *args, **kwargs + ) + + 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 RuleExecutionErrorServiceClient.get_mtls_endpoint_and_cert_source( + client_options + ) # type: ignore + + @property + def transport(self) -> RuleExecutionErrorServiceTransport: + """Returns the transport used by the client instance. + + Returns: + RuleExecutionErrorServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self) -> str: + """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 = RuleExecutionErrorServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, + RuleExecutionErrorServiceTransport, + Callable[..., RuleExecutionErrorServiceTransport], + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the rule execution error service async client. + + Args: + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + transport (Optional[Union[str,RuleExecutionErrorServiceTransport,Callable[..., RuleExecutionErrorServiceTransport]]]): + The transport to use, or a Callable that constructs and returns a new transport to use. + If a Callable is given, it will be called with the same set of initialization + arguments as used in the RuleExecutionErrorServiceTransport constructor. + If set to None, a transport is chosen automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): + Custom options for the client. + + 1. The ``api_endpoint`` property can be used to override the + default endpoint provided by the client when ``transport`` is + not explicitly provided. Only if this property is not set and + ``transport`` was not explicitly provided, the endpoint is + determined by the GOOGLE_API_USE_MTLS_ENDPOINT environment + variable, which have one of the following values: + "always" (always use the default mTLS endpoint), "never" (always + use the default regular endpoint) and "auto" (auto-switch to the + default mTLS endpoint if client certificate is present; this is + the default value). + + 2. If the GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide a client certificate for mTLS transport. If + not provided, the default SSL client certificate will be used if + present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not + set, no client certificate will be used. + + 3. The ``universe_domain`` property can be used to override the + default "googleapis.com" universe. Note that ``api_endpoint`` + property still takes precedence; and ``universe_domain`` is + currently not supported for mTLS. + + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + + Raises: + google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport + creation failed for any reason. + """ + self._client = RuleExecutionErrorServiceClient( + credentials=credentials, + transport=transport, + client_options=client_options, + client_info=client_info, + ) + + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + std_logging.DEBUG + ): # pragma: NO COVER + _LOGGER.debug( + "Created client `google.cloud.chronicle_v1.RuleExecutionErrorServiceAsyncClient`.", + extra={ + "serviceName": "google.cloud.chronicle.v1.RuleExecutionErrorService", + "universeDomain": getattr( + self._client._transport._credentials, "universe_domain", "" + ), + "credentialsType": f"{type(self._client._transport._credentials).__module__}.{type(self._client._transport._credentials).__qualname__}", + "credentialsInfo": getattr( + self.transport._credentials, "get_cred_info", lambda: None + )(), + } + if hasattr(self._client._transport, "_credentials") + else { + "serviceName": "google.cloud.chronicle.v1.RuleExecutionErrorService", + "credentialsType": None, + }, + ) + + async def list_rule_execution_errors( + self, + request: Optional[ + Union[rule_execution_error.ListRuleExecutionErrorsRequest, dict] + ] = None, + *, + parent: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> pagers.ListRuleExecutionErrorsAsyncPager: + r"""Lists rule execution errors. + + .. 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 chronicle_v1 + + async def sample_list_rule_execution_errors(): + # Create a client + client = chronicle_v1.RuleExecutionErrorServiceAsyncClient() + + # Initialize request argument(s) + request = chronicle_v1.ListRuleExecutionErrorsRequest( + parent="parent_value", + ) + + # Make the request + page_result = client.list_rule_execution_errors(request=request) + + # Handle the response + async for response in page_result: + print(response) + + Args: + request (Optional[Union[google.cloud.chronicle_v1.types.ListRuleExecutionErrorsRequest, dict]]): + The request object. Request message for + ListRuleExecutionErrors. + parent (:class:`str`): + Required. The instance to list rule + execution errors from. Format: + + projects/{project}/locations/{location}/instances/{instance} + + 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + google.cloud.chronicle_v1.services.rule_execution_error_service.pagers.ListRuleExecutionErrorsAsyncPager: + Response message for + ListRuleExecutionErrors. + 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. + flattened_params = [parent] + has_flattened_params = ( + len([param for param in flattened_params if param is not None]) > 0 + ) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, rule_execution_error.ListRuleExecutionErrorsRequest): + request = rule_execution_error.ListRuleExecutionErrorsRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if parent is not None: + request.parent = parent + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.list_rule_execution_errors + ] + + # 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.ListRuleExecutionErrorsAsyncPager( + method=rpc, + request=request, + response=response, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def list_operations( + self, + request: Optional[Union[operations_pb2.ListOperationsRequest, dict]] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + 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 request is None: + request_pb = operations_pb2.ListOperationsRequest() + elif isinstance(request, dict): + request_pb = operations_pb2.ListOperationsRequest(**request) + else: + request_pb = request + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self.transport._wrapped_methods[self._client._transport.list_operations] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request_pb.name),)), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request_pb, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def get_operation( + self, + request: Optional[Union[operations_pb2.GetOperationRequest, dict]] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + 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 request is None: + request_pb = operations_pb2.GetOperationRequest() + elif isinstance(request, dict): + request_pb = operations_pb2.GetOperationRequest(**request) + else: + request_pb = request + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self.transport._wrapped_methods[self._client._transport.get_operation] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request_pb.name),)), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request_pb, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def delete_operation( + self, + request: Optional[Union[operations_pb2.DeleteOperationRequest, dict]] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> None: + r"""Deletes a long-running operation. + + This method indicates that the client is no longer interested + in the operation result. It does not cancel the operation. + If the server doesn't support this method, it returns + `google.rpc.Code.UNIMPLEMENTED`. + + Args: + request (:class:`~.operations_pb2.DeleteOperationRequest`): + The request object. Request message for + `DeleteOperation` 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + Returns: + None + """ + # 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 request is None: + request_pb = operations_pb2.DeleteOperationRequest() + elif isinstance(request, dict): + request_pb = operations_pb2.DeleteOperationRequest(**request) + else: + request_pb = request + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self.transport._wrapped_methods[self._client._transport.delete_operation] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request_pb.name),)), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + await rpc( + request_pb, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + async def cancel_operation( + self, + request: Optional[Union[operations_pb2.CancelOperationRequest, dict]] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> None: + r"""Starts asynchronous cancellation on a long-running operation. + + The server makes a best effort to cancel the operation, but success + is not guaranteed. If the server doesn't support this method, it returns + `google.rpc.Code.UNIMPLEMENTED`. + + Args: + request (:class:`~.operations_pb2.CancelOperationRequest`): + The request object. Request message for + `CancelOperation` 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + Returns: + None + """ + # 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 request is None: + request_pb = operations_pb2.CancelOperationRequest() + elif isinstance(request, dict): + request_pb = operations_pb2.CancelOperationRequest(**request) + else: + request_pb = request + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self.transport._wrapped_methods[self._client._transport.cancel_operation] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request_pb.name),)), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + await rpc( + request_pb, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + async def __aenter__(self) -> "RuleExecutionErrorServiceAsyncClient": + 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__ +) + +if hasattr(DEFAULT_CLIENT_INFO, "protobuf_runtime_version"): # pragma: NO COVER + DEFAULT_CLIENT_INFO.protobuf_runtime_version = google.protobuf.__version__ + + +__all__ = ("RuleExecutionErrorServiceAsyncClient",) diff --git a/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_execution_error_service/client.py b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_execution_error_service/client.py new file mode 100644 index 000000000000..776dc45f3acf --- /dev/null +++ b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_execution_error_service/client.py @@ -0,0 +1,1188 @@ +# -*- coding: utf-8 -*- +# Copyright 2026 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 json +import logging as std_logging +import os +import re +import warnings +from collections import OrderedDict +from http import HTTPStatus +from typing import ( + Callable, + Dict, + Mapping, + MutableMapping, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) + +import google.protobuf +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.chronicle_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 + +try: + from google.api_core import client_logging # type: ignore + + CLIENT_LOGGING_SUPPORTED = True # pragma: NO COVER +except ImportError: # pragma: NO COVER + CLIENT_LOGGING_SUPPORTED = False + +_LOGGER = std_logging.getLogger(__name__) + +from google.longrunning import operations_pb2 # type: ignore + +from google.cloud.chronicle_v1.services.rule_execution_error_service import pagers +from google.cloud.chronicle_v1.types import rule_execution_error + +from .transports.base import DEFAULT_CLIENT_INFO, RuleExecutionErrorServiceTransport +from .transports.grpc import RuleExecutionErrorServiceGrpcTransport +from .transports.grpc_asyncio import RuleExecutionErrorServiceGrpcAsyncIOTransport +from .transports.rest import RuleExecutionErrorServiceRestTransport + + +class RuleExecutionErrorServiceClientMeta(type): + """Metaclass for the RuleExecutionErrorService 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[RuleExecutionErrorServiceTransport]] + _transport_registry["grpc"] = RuleExecutionErrorServiceGrpcTransport + _transport_registry["grpc_asyncio"] = RuleExecutionErrorServiceGrpcAsyncIOTransport + _transport_registry["rest"] = RuleExecutionErrorServiceRestTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[RuleExecutionErrorServiceTransport]: + """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 RuleExecutionErrorServiceClient(metaclass=RuleExecutionErrorServiceClientMeta): + """RuleExecutionErrorService contains endpoints related to rule + execution errors. + """ + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint) -> Optional[str]: + """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: + Optional[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) + if m is None: + # Could not parse api_endpoint; return as-is. + return 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 = "chronicle.googleapis.com" + DEFAULT_MTLS_ENDPOINT = _get_default_mtls_endpoint.__func__( # type: ignore + DEFAULT_ENDPOINT + ) + + _DEFAULT_ENDPOINT_TEMPLATE = "chronicle.{UNIVERSE_DOMAIN}" + _DEFAULT_UNIVERSE = "googleapis.com" + + @staticmethod + def _use_client_cert_effective(): + """Returns whether client certificate should be used for mTLS if the + google-auth version supports should_use_client_cert automatic mTLS enablement. + + Alternatively, read from the GOOGLE_API_USE_CLIENT_CERTIFICATE env var. + + Returns: + bool: whether client certificate should be used for mTLS + Raises: + ValueError: (If using a version of google-auth without should_use_client_cert and + GOOGLE_API_USE_CLIENT_CERTIFICATE is set to an unexpected value.) + """ + # check if google-auth version supports should_use_client_cert for automatic mTLS enablement + if hasattr(mtls, "should_use_client_cert"): # pragma: NO COVER + return mtls.should_use_client_cert() + else: # pragma: NO COVER + # if unsupported, fallback to reading from env var + use_client_cert_str = os.getenv( + "GOOGLE_API_USE_CLIENT_CERTIFICATE", "false" + ).lower() + if use_client_cert_str not in ("true", "false"): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be" + " either `true` or `false`" + ) + return use_client_cert_str == "true" + + @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: + RuleExecutionErrorServiceClient: 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: + RuleExecutionErrorServiceClient: 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) -> RuleExecutionErrorServiceTransport: + """Returns the transport used by the client instance. + + Returns: + RuleExecutionErrorServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def curated_rule_path( + project: str, + location: str, + instance: str, + curatedRule: str, + ) -> str: + """Returns a fully-qualified curated_rule string.""" + return "projects/{project}/locations/{location}/instances/{instance}/curatedRules/{curatedRule}".format( + project=project, + location=location, + instance=instance, + curatedRule=curatedRule, + ) + + @staticmethod + def parse_curated_rule_path(path: str) -> Dict[str, str]: + """Parses a curated_rule path into its component segments.""" + m = re.match( + r"^projects/(?P.+?)/locations/(?P.+?)/instances/(?P.+?)/curatedRules/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def rule_path( + project: str, + location: str, + instance: str, + rule: str, + ) -> str: + """Returns a fully-qualified rule string.""" + return "projects/{project}/locations/{location}/instances/{instance}/rules/{rule}".format( + project=project, + location=location, + instance=instance, + rule=rule, + ) + + @staticmethod + def parse_rule_path(path: str) -> Dict[str, str]: + """Parses a rule path into its component segments.""" + m = re.match( + r"^projects/(?P.+?)/locations/(?P.+?)/instances/(?P.+?)/rules/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def rule_execution_error_path( + project: str, + location: str, + instance: str, + rule_execution_error: str, + ) -> str: + """Returns a fully-qualified rule_execution_error string.""" + return "projects/{project}/locations/{location}/instances/{instance}/ruleExecutionErrors/{rule_execution_error}".format( + project=project, + location=location, + instance=instance, + rule_execution_error=rule_execution_error, + ) + + @staticmethod + def parse_rule_execution_error_path(path: str) -> Dict[str, str]: + """Parses a rule_execution_error path into its component segments.""" + m = re.match( + r"^projects/(?P.+?)/locations/(?P.+?)/instances/(?P.+?)/ruleExecutionErrors/(?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 = RuleExecutionErrorServiceClient._use_client_cert_effective() + use_mtls_endpoint = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + 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: + 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 = RuleExecutionErrorServiceClient._use_client_cert_effective() + use_mtls_endpoint = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto").lower() + universe_domain_env = os.getenv("GOOGLE_CLOUD_UNIVERSE_DOMAIN") + 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, 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 + ) -> str: + """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 = RuleExecutionErrorServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = RuleExecutionErrorServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = ( + RuleExecutionErrorServiceClient._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 = RuleExecutionErrorServiceClient._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 + + 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. + """ + + # NOTE (b/349488459): universe validation is disabled until further notice. + return True + + def _add_cred_info_for_auth_errors( + self, error: core_exceptions.GoogleAPICallError + ) -> None: + """Adds credential info string to error details for 401/403/404 errors. + + Args: + error (google.api_core.exceptions.GoogleAPICallError): The error to add the cred info. + """ + if error.code not in [ + HTTPStatus.UNAUTHORIZED, + HTTPStatus.FORBIDDEN, + HTTPStatus.NOT_FOUND, + ]: + return + + cred = self._transport._credentials + + # get_cred_info is only available in google-auth>=2.35.0 + if not hasattr(cred, "get_cred_info"): + return + + # ignore the type check since pypy test fails when get_cred_info + # is not available + cred_info = cred.get_cred_info() # type: ignore + if cred_info and hasattr(error._details, "append"): + error._details.append(json.dumps(cred_info)) + + @property + def api_endpoint(self) -> str: + """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, + RuleExecutionErrorServiceTransport, + Callable[..., RuleExecutionErrorServiceTransport], + ] + ] = None, + client_options: Optional[Union[client_options_lib.ClientOptions, dict]] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the rule execution error service client. + + Args: + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + transport (Optional[Union[str,RuleExecutionErrorServiceTransport,Callable[..., RuleExecutionErrorServiceTransport]]]): + The transport to use, or a Callable that constructs and returns a new transport. + If a Callable is given, it will be called with the same set of initialization + arguments as used in the RuleExecutionErrorServiceTransport constructor. + If set to None, a transport is chosen automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): + Custom options for the client. + + 1. The ``api_endpoint`` property can be used to override the + default endpoint provided by the client when ``transport`` is + not explicitly provided. Only if this property is not set and + ``transport`` was not explicitly provided, the endpoint is + determined by the GOOGLE_API_USE_MTLS_ENDPOINT environment + variable, which have one of the following values: + "always" (always use the default mTLS endpoint), "never" (always + use the default regular endpoint) and "auto" (auto-switch to the + default mTLS endpoint if client certificate is present; this is + the default value). + + 2. If the GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide a client certificate for mTLS transport. If + not provided, the default SSL client certificate will be used if + present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not + set, no client certificate will be used. + + 3. The ``universe_domain`` property can be used to override the + default "googleapis.com" universe. Note that the ``api_endpoint`` + property still takes precedence; and ``universe_domain`` is + currently not supported for mTLS. + + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + """ + self._client_options = client_options + if isinstance(self._client_options, dict): + self._client_options = client_options_lib.from_dict(self._client_options) + if self._client_options is None: + self._client_options = client_options_lib.ClientOptions() + self._client_options = cast( + client_options_lib.ClientOptions, self._client_options + ) + + universe_domain_opt = getattr(self._client_options, "universe_domain", None) + + self._use_client_cert, self._use_mtls_endpoint, self._universe_domain_env = ( + RuleExecutionErrorServiceClient._read_environment_variables() + ) + self._client_cert_source = ( + RuleExecutionErrorServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + ) + self._universe_domain = RuleExecutionErrorServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + self._api_endpoint: str = "" # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + if CLIENT_LOGGING_SUPPORTED: # pragma: NO COVER + # Setup logging. + client_logging.initialize_logging() + + 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, RuleExecutionErrorServiceTransport) + if transport_provided: + # transport is a RuleExecutionErrorServiceTransport 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(RuleExecutionErrorServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or RuleExecutionErrorServiceClient._get_api_endpoint( + self._client_options.api_endpoint, + self._client_cert_source, + self._universe_domain, + self._use_mtls_endpoint, + ) + ) + + if not transport_provided: + import google.auth._default # type: ignore + + if api_key_value and hasattr( + google.auth._default, "get_api_key_credentials" + ): + credentials = google.auth._default.get_api_key_credentials( + api_key_value + ) + + transport_init: Union[ + Type[RuleExecutionErrorServiceTransport], + Callable[..., RuleExecutionErrorServiceTransport], + ] = ( + RuleExecutionErrorServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast(Callable[..., RuleExecutionErrorServiceTransport], transport) + ) + # initialize with the provided callable or the passed in class + self._transport = transport_init( + credentials=credentials, + credentials_file=self._client_options.credentials_file, + host=self._api_endpoint, + scopes=self._client_options.scopes, + client_cert_source_for_mtls=self._client_cert_source, + quota_project_id=self._client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + api_audience=self._client_options.api_audience, + ) + + if "async" not in str(self._transport): + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + std_logging.DEBUG + ): # pragma: NO COVER + _LOGGER.debug( + "Created client `google.cloud.chronicle_v1.RuleExecutionErrorServiceClient`.", + extra={ + "serviceName": "google.cloud.chronicle.v1.RuleExecutionErrorService", + "universeDomain": getattr( + self._transport._credentials, "universe_domain", "" + ), + "credentialsType": f"{type(self._transport._credentials).__module__}.{type(self._transport._credentials).__qualname__}", + "credentialsInfo": getattr( + self.transport._credentials, "get_cred_info", lambda: None + )(), + } + if hasattr(self._transport, "_credentials") + else { + "serviceName": "google.cloud.chronicle.v1.RuleExecutionErrorService", + "credentialsType": None, + }, + ) + + def list_rule_execution_errors( + self, + request: Optional[ + Union[rule_execution_error.ListRuleExecutionErrorsRequest, dict] + ] = None, + *, + parent: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> pagers.ListRuleExecutionErrorsPager: + r"""Lists rule execution errors. + + .. 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 chronicle_v1 + + def sample_list_rule_execution_errors(): + # Create a client + client = chronicle_v1.RuleExecutionErrorServiceClient() + + # Initialize request argument(s) + request = chronicle_v1.ListRuleExecutionErrorsRequest( + parent="parent_value", + ) + + # Make the request + page_result = client.list_rule_execution_errors(request=request) + + # Handle the response + for response in page_result: + print(response) + + Args: + request (Union[google.cloud.chronicle_v1.types.ListRuleExecutionErrorsRequest, dict]): + The request object. Request message for + ListRuleExecutionErrors. + parent (str): + Required. The instance to list rule + execution errors from. Format: + + projects/{project}/locations/{location}/instances/{instance} + + 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + google.cloud.chronicle_v1.services.rule_execution_error_service.pagers.ListRuleExecutionErrorsPager: + Response message for + ListRuleExecutionErrors. + 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. + flattened_params = [parent] + has_flattened_params = ( + len([param for param in flattened_params if param is not None]) > 0 + ) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, rule_execution_error.ListRuleExecutionErrorsRequest): + request = rule_execution_error.ListRuleExecutionErrorsRequest(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_rule_execution_errors + ] + + # 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.ListRuleExecutionErrorsPager( + method=rpc, + request=request, + response=response, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + def __enter__(self) -> "RuleExecutionErrorServiceClient": + 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[Union[operations_pb2.ListOperationsRequest, dict]] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + 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 request is None: + request_pb = operations_pb2.ListOperationsRequest() + elif isinstance(request, dict): + request_pb = operations_pb2.ListOperationsRequest(**request) + else: + request_pb = request + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.list_operations] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request_pb.name),)), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + try: + # Send the request. + response = rpc( + request_pb, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + except core_exceptions.GoogleAPICallError as e: + self._add_cred_info_for_auth_errors(e) + raise e + + def get_operation( + self, + request: Optional[Union[operations_pb2.GetOperationRequest, dict]] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + 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 request is None: + request_pb = operations_pb2.GetOperationRequest() + elif isinstance(request, dict): + request_pb = operations_pb2.GetOperationRequest(**request) + else: + request_pb = request + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.get_operation] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request_pb.name),)), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + try: + # Send the request. + response = rpc( + request_pb, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + except core_exceptions.GoogleAPICallError as e: + self._add_cred_info_for_auth_errors(e) + raise e + + def delete_operation( + self, + request: Optional[Union[operations_pb2.DeleteOperationRequest, dict]] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> None: + r"""Deletes a long-running operation. + + This method indicates that the client is no longer interested + in the operation result. It does not cancel the operation. + If the server doesn't support this method, it returns + `google.rpc.Code.UNIMPLEMENTED`. + + Args: + request (:class:`~.operations_pb2.DeleteOperationRequest`): + The request object. Request message for + `DeleteOperation` 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + Returns: + None + """ + # 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 request is None: + request_pb = operations_pb2.DeleteOperationRequest() + elif isinstance(request, dict): + request_pb = operations_pb2.DeleteOperationRequest(**request) + else: + request_pb = request + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.delete_operation] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request_pb.name),)), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + rpc( + request_pb, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + def cancel_operation( + self, + request: Optional[Union[operations_pb2.CancelOperationRequest, dict]] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> None: + r"""Starts asynchronous cancellation on a long-running operation. + + The server makes a best effort to cancel the operation, but success + is not guaranteed. If the server doesn't support this method, it returns + `google.rpc.Code.UNIMPLEMENTED`. + + Args: + request (:class:`~.operations_pb2.CancelOperationRequest`): + The request object. Request message for + `CancelOperation` 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + Returns: + None + """ + # 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 request is None: + request_pb = operations_pb2.CancelOperationRequest() + elif isinstance(request, dict): + request_pb = operations_pb2.CancelOperationRequest(**request) + else: + request_pb = request + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.cancel_operation] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request_pb.name),)), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + rpc( + request_pb, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + +DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=package_version.__version__ +) + +if hasattr(DEFAULT_CLIENT_INFO, "protobuf_runtime_version"): # pragma: NO COVER + DEFAULT_CLIENT_INFO.protobuf_runtime_version = google.protobuf.__version__ + +__all__ = ("RuleExecutionErrorServiceClient",) diff --git a/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_execution_error_service/pagers.py b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_execution_error_service/pagers.py new file mode 100644 index 000000000000..d3c8caec0a00 --- /dev/null +++ b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_execution_error_service/pagers.py @@ -0,0 +1,201 @@ +# -*- coding: utf-8 -*- +# Copyright 2026 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 ( + Any, + AsyncIterator, + Awaitable, + Callable, + Iterator, + Optional, + Sequence, + Tuple, + Union, +) + +from google.api_core import gapic_v1 +from google.api_core import retry as retries +from google.api_core import retry_async as retries_async + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault, None] + OptionalAsyncRetry = Union[ + retries_async.AsyncRetry, gapic_v1.method._MethodDefault, None + ] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object, None] # type: ignore + OptionalAsyncRetry = Union[retries_async.AsyncRetry, object, None] # type: ignore + +from google.cloud.chronicle_v1.types import rule_execution_error + + +class ListRuleExecutionErrorsPager: + """A pager for iterating through ``list_rule_execution_errors`` requests. + + This class thinly wraps an initial + :class:`google.cloud.chronicle_v1.types.ListRuleExecutionErrorsResponse` object, and + provides an ``__iter__`` method to iterate through its + ``rule_execution_errors`` field. + + If there are more pages, the ``__iter__`` method will make additional + ``ListRuleExecutionErrors`` requests and continue to iterate + through the ``rule_execution_errors`` field on the + corresponding responses. + + All the usual :class:`google.cloud.chronicle_v1.types.ListRuleExecutionErrorsResponse` + 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[..., rule_execution_error.ListRuleExecutionErrorsResponse], + request: rule_execution_error.ListRuleExecutionErrorsRequest, + response: rule_execution_error.ListRuleExecutionErrorsResponse, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ): + """Instantiate the pager. + + Args: + method (Callable): The method that was originally called, and + which instantiated this pager. + request (google.cloud.chronicle_v1.types.ListRuleExecutionErrorsRequest): + The initial request object. + response (google.cloud.chronicle_v1.types.ListRuleExecutionErrorsResponse): + The initial response object. + 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + """ + self._method = method + self._request = rule_execution_error.ListRuleExecutionErrorsRequest(request) + self._response = response + self._retry = retry + self._timeout = timeout + self._metadata = metadata + + def __getattr__(self, name: str) -> Any: + return getattr(self._response, name) + + @property + def pages(self) -> Iterator[rule_execution_error.ListRuleExecutionErrorsResponse]: + yield self._response + while self._response.next_page_token: + self._request.page_token = self._response.next_page_token + self._response = self._method( + self._request, + retry=self._retry, + timeout=self._timeout, + metadata=self._metadata, + ) + yield self._response + + def __iter__(self) -> Iterator[rule_execution_error.RuleExecutionError]: + for page in self.pages: + yield from page.rule_execution_errors + + def __repr__(self) -> str: + return "{0}<{1!r}>".format(self.__class__.__name__, self._response) + + +class ListRuleExecutionErrorsAsyncPager: + """A pager for iterating through ``list_rule_execution_errors`` requests. + + This class thinly wraps an initial + :class:`google.cloud.chronicle_v1.types.ListRuleExecutionErrorsResponse` object, and + provides an ``__aiter__`` method to iterate through its + ``rule_execution_errors`` field. + + If there are more pages, the ``__aiter__`` method will make additional + ``ListRuleExecutionErrors`` requests and continue to iterate + through the ``rule_execution_errors`` field on the + corresponding responses. + + All the usual :class:`google.cloud.chronicle_v1.types.ListRuleExecutionErrorsResponse` + 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[rule_execution_error.ListRuleExecutionErrorsResponse] + ], + request: rule_execution_error.ListRuleExecutionErrorsRequest, + response: rule_execution_error.ListRuleExecutionErrorsResponse, + *, + retry: OptionalAsyncRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ): + """Instantiates the pager. + + Args: + method (Callable): The method that was originally called, and + which instantiated this pager. + request (google.cloud.chronicle_v1.types.ListRuleExecutionErrorsRequest): + The initial request object. + response (google.cloud.chronicle_v1.types.ListRuleExecutionErrorsResponse): + The initial response object. + retry (google.api_core.retry.AsyncRetry): Designation of what errors, + if any, should be retried. + timeout (float): The timeout for this request. + metadata (Sequence[Tuple[str, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + """ + self._method = method + self._request = rule_execution_error.ListRuleExecutionErrorsRequest(request) + self._response = response + self._retry = retry + self._timeout = timeout + self._metadata = metadata + + def __getattr__(self, name: str) -> Any: + return getattr(self._response, name) + + @property + async def pages( + self, + ) -> AsyncIterator[rule_execution_error.ListRuleExecutionErrorsResponse]: + 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, + retry=self._retry, + timeout=self._timeout, + metadata=self._metadata, + ) + yield self._response + + def __aiter__(self) -> AsyncIterator[rule_execution_error.RuleExecutionError]: + async def async_generator(): + async for page in self.pages: + for response in page.rule_execution_errors: + 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-chronicle/google/cloud/chronicle_v1/services/rule_execution_error_service/transports/README.rst b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_execution_error_service/transports/README.rst new file mode 100644 index 000000000000..3fbe22612bd7 --- /dev/null +++ b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_execution_error_service/transports/README.rst @@ -0,0 +1,10 @@ + +transport inheritance structure +_______________________________ + +``RuleExecutionErrorServiceTransport`` is the ABC for all transports. + +- public child ``RuleExecutionErrorServiceGrpcTransport`` for sync gRPC transport (defined in ``grpc.py``). +- public child ``RuleExecutionErrorServiceGrpcAsyncIOTransport`` for async gRPC transport (defined in ``grpc_asyncio.py``). +- private child ``_BaseRuleExecutionErrorServiceRestTransport`` for base REST transport with inner classes ``_BaseMETHOD`` (defined in ``rest_base.py``). +- public child ``RuleExecutionErrorServiceRestTransport`` for sync REST transport with inner classes ``METHOD`` derived from the parent's corresponding ``_BaseMETHOD`` classes (defined in ``rest.py``). diff --git a/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_execution_error_service/transports/__init__.py b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_execution_error_service/transports/__init__.py new file mode 100644 index 000000000000..79b16393ae0e --- /dev/null +++ b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_execution_error_service/transports/__init__.py @@ -0,0 +1,39 @@ +# -*- coding: utf-8 -*- +# Copyright 2026 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 RuleExecutionErrorServiceTransport +from .grpc import RuleExecutionErrorServiceGrpcTransport +from .grpc_asyncio import RuleExecutionErrorServiceGrpcAsyncIOTransport +from .rest import ( + RuleExecutionErrorServiceRestInterceptor, + RuleExecutionErrorServiceRestTransport, +) + +# Compile a registry of transports. +_transport_registry = OrderedDict() # type: Dict[str, Type[RuleExecutionErrorServiceTransport]] +_transport_registry["grpc"] = RuleExecutionErrorServiceGrpcTransport +_transport_registry["grpc_asyncio"] = RuleExecutionErrorServiceGrpcAsyncIOTransport +_transport_registry["rest"] = RuleExecutionErrorServiceRestTransport + +__all__ = ( + "RuleExecutionErrorServiceTransport", + "RuleExecutionErrorServiceGrpcTransport", + "RuleExecutionErrorServiceGrpcAsyncIOTransport", + "RuleExecutionErrorServiceRestTransport", + "RuleExecutionErrorServiceRestInterceptor", +) diff --git a/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_execution_error_service/transports/base.py b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_execution_error_service/transports/base.py new file mode 100644 index 000000000000..c69c33dbe21f --- /dev/null +++ b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_execution_error_service/transports/base.py @@ -0,0 +1,251 @@ +# -*- coding: utf-8 -*- +# Copyright 2026 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 +import google.auth # type: ignore +import google.protobuf +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.longrunning import operations_pb2 # type: ignore +from google.oauth2 import service_account # type: ignore + +from google.cloud.chronicle_v1 import gapic_version as package_version +from google.cloud.chronicle_v1.types import rule_execution_error + +DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=package_version.__version__ +) + +if hasattr(DEFAULT_CLIENT_INFO, "protobuf_runtime_version"): # pragma: NO COVER + DEFAULT_CLIENT_INFO.protobuf_runtime_version = google.protobuf.__version__ + + +class RuleExecutionErrorServiceTransport(abc.ABC): + """Abstract transport class for RuleExecutionErrorService.""" + + AUTH_SCOPES = ( + "https://www.googleapis.com/auth/chronicle", + "https://www.googleapis.com/auth/chronicle.readonly", + "https://www.googleapis.com/auth/cloud-platform", + ) + + DEFAULT_HOST: str = "chronicle.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: 'chronicle.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]): Deprecated. A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. This argument will be + removed in the next major version of this library. + 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. + api_audience (Optional[str]): The intended audience for the API calls + to the service that will be set when using certain 3rd party + authentication flows. Audience is typically a resource identifier. + If not set, the host value will be used as a default. + """ + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + default_scopes=self.AUTH_SCOPES, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + scopes=scopes, + quota_project_id=quota_project_id, + default_scopes=self.AUTH_SCOPES, + ) + # 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 + + self._wrapped_methods: Dict[Callable, Callable] = {} + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.list_rule_execution_errors: gapic_v1.method.wrap_method( + self.list_rule_execution_errors, + default_retry=retries.Retry( + initial=1.0, + maximum=600.0, + multiplier=1.3, + predicate=retries.if_exception_type( + core_exceptions.ServiceUnavailable, + ), + deadline=600.0, + ), + default_timeout=600.0, + client_info=client_info, + ), + self.cancel_operation: gapic_v1.method.wrap_method( + self.cancel_operation, + default_timeout=None, + client_info=client_info, + ), + self.delete_operation: gapic_v1.method.wrap_method( + self.delete_operation, + default_timeout=None, + client_info=client_info, + ), + self.get_operation: gapic_v1.method.wrap_method( + self.get_operation, + default_timeout=None, + client_info=client_info, + ), + self.list_operations: gapic_v1.method.wrap_method( + self.list_operations, + 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 list_rule_execution_errors( + self, + ) -> Callable[ + [rule_execution_error.ListRuleExecutionErrorsRequest], + Union[ + rule_execution_error.ListRuleExecutionErrorsResponse, + Awaitable[rule_execution_error.ListRuleExecutionErrorsResponse], + ], + ]: + 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 cancel_operation( + self, + ) -> Callable[ + [operations_pb2.CancelOperationRequest], + None, + ]: + raise NotImplementedError() + + @property + def delete_operation( + self, + ) -> Callable[ + [operations_pb2.DeleteOperationRequest], + None, + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("RuleExecutionErrorServiceTransport",) diff --git a/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_execution_error_service/transports/grpc.py b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_execution_error_service/transports/grpc.py new file mode 100644 index 000000000000..042756eb18da --- /dev/null +++ b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_execution_error_service/transports/grpc.py @@ -0,0 +1,439 @@ +# -*- coding: utf-8 -*- +# Copyright 2026 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 json +import logging as std_logging +import pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +import google.auth # type: ignore +import google.protobuf.message +import grpc # type: ignore +import proto # type: ignore +from google.api_core import gapic_v1, grpc_helpers +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.longrunning import operations_pb2 # type: ignore +from google.protobuf.json_format import MessageToJson + +from google.cloud.chronicle_v1.types import rule_execution_error + +from .base import DEFAULT_CLIENT_INFO, RuleExecutionErrorServiceTransport + +try: + from google.api_core import client_logging # type: ignore + + CLIENT_LOGGING_SUPPORTED = True # pragma: NO COVER +except ImportError: # pragma: NO COVER + CLIENT_LOGGING_SUPPORTED = False + +_LOGGER = std_logging.getLogger(__name__) + + +class _LoggingClientInterceptor(grpc.UnaryUnaryClientInterceptor): # pragma: NO COVER + def intercept_unary_unary(self, continuation, client_call_details, request): + logging_enabled = CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + std_logging.DEBUG + ) + if logging_enabled: # pragma: NO COVER + request_metadata = client_call_details.metadata + if isinstance(request, proto.Message): + request_payload = type(request).to_json(request) + elif isinstance(request, google.protobuf.message.Message): + request_payload = MessageToJson(request) + else: + request_payload = f"{type(request).__name__}: {pickle.dumps(request)!r}" + + request_metadata = { + key: value.decode("utf-8") if isinstance(value, bytes) else value + for key, value in request_metadata + } + grpc_request = { + "payload": request_payload, + "requestMethod": "grpc", + "metadata": dict(request_metadata), + } + _LOGGER.debug( + f"Sending request for {client_call_details.method}", + extra={ + "serviceName": "google.cloud.chronicle.v1.RuleExecutionErrorService", + "rpcName": str(client_call_details.method), + "request": grpc_request, + "metadata": grpc_request["metadata"], + }, + ) + response = continuation(client_call_details, request) + if logging_enabled: # pragma: NO COVER + response_metadata = response.trailing_metadata() + # Convert gRPC metadata `` to list of tuples + metadata = ( + dict([(k, str(v)) for k, v in response_metadata]) + if response_metadata + else None + ) + result = response.result() + if isinstance(result, proto.Message): + response_payload = type(result).to_json(result) + elif isinstance(result, google.protobuf.message.Message): + response_payload = MessageToJson(result) + else: + response_payload = f"{type(result).__name__}: {pickle.dumps(result)!r}" + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.cloud.chronicle.v1.RuleExecutionErrorService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class RuleExecutionErrorServiceGrpcTransport(RuleExecutionErrorServiceTransport): + """gRPC backend transport for RuleExecutionErrorService. + + RuleExecutionErrorService contains endpoints related to rule + execution errors. + + 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 = "chronicle.googleapis.com", + credentials: Optional[ga_credentials.Credentials] = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + channel: Optional[Union[grpc.Channel, Callable[..., grpc.Channel]]] = None, + api_mtls_endpoint: Optional[str] = None, + client_cert_source: Optional[Callable[[], Tuple[bytes, bytes]]] = None, + ssl_channel_credentials: Optional[grpc.ChannelCredentials] = None, + client_cert_source_for_mtls: Optional[Callable[[], Tuple[bytes, bytes]]] = None, + quota_project_id: Optional[str] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, + api_audience: Optional[str] = None, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to (default: 'chronicle.googleapis.com'). + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if a ``channel`` instance is provided. + credentials_file (Optional[str]): Deprecated. A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if a ``channel`` instance is provided. + This argument will be removed in the next major version of this library. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if a ``channel`` instance is provided. + channel (Optional[Union[grpc.Channel, Callable[..., grpc.Channel]]]): + A ``Channel`` instance through which to make calls, or a Callable + that constructs and returns one. If set to None, ``self.create_channel`` + is used to create the channel. If a Callable is given, it will be called + with the same arguments as used in ``self.create_channel``. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if a ``channel`` instance is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if a ``channel`` instance or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + api_audience (Optional[str]): The intended audience for the API calls + to the service that will be set when using certain 3rd party + authentication flows. Audience is typically a resource identifier. + If not set, the host value will be used as a default. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn("client_cert_source is deprecated", DeprecationWarning) + + if isinstance(channel, grpc.Channel): + # Ignore credentials if a channel was passed. + credentials = None + self._ignore_credentials = True + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + else: + self._ssl_channel_credentials = SslCredentials().ssl_credentials + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + api_audience=api_audience, + ) + + if not self._grpc_channel: + # initialize with the provided callable or the default channel + channel_init = channel or type(self).create_channel + self._grpc_channel = channel_init( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + self._interceptor = _LoggingClientInterceptor() + self._logged_channel = grpc.intercept_channel( + self._grpc_channel, self._interceptor + ) + + # Wrap messages. This must be done after self._logged_channel exists + self._prep_wrapped_messages(client_info) + + @classmethod + def create_channel( + cls, + host: str = "chronicle.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]): Deprecated. A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. This argument will be + removed in the next major version of this library. + 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 list_rule_execution_errors( + self, + ) -> Callable[ + [rule_execution_error.ListRuleExecutionErrorsRequest], + rule_execution_error.ListRuleExecutionErrorsResponse, + ]: + r"""Return a callable for the list rule execution errors method over gRPC. + + Lists rule execution errors. + + Returns: + Callable[[~.ListRuleExecutionErrorsRequest], + ~.ListRuleExecutionErrorsResponse]: + 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_rule_execution_errors" not in self._stubs: + self._stubs["list_rule_execution_errors"] = ( + self._logged_channel.unary_unary( + "/google.cloud.chronicle.v1.RuleExecutionErrorService/ListRuleExecutionErrors", + request_serializer=rule_execution_error.ListRuleExecutionErrorsRequest.serialize, + response_deserializer=rule_execution_error.ListRuleExecutionErrorsResponse.deserialize, + ) + ) + return self._stubs["list_rule_execution_errors"] + + def close(self): + self._logged_channel.close() + + @property + def delete_operation( + self, + ) -> Callable[[operations_pb2.DeleteOperationRequest], None]: + r"""Return a callable for the delete_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 "delete_operation" not in self._stubs: + self._stubs["delete_operation"] = self._logged_channel.unary_unary( + "/google.longrunning.Operations/DeleteOperation", + request_serializer=operations_pb2.DeleteOperationRequest.SerializeToString, + response_deserializer=None, + ) + return self._stubs["delete_operation"] + + @property + def cancel_operation( + self, + ) -> Callable[[operations_pb2.CancelOperationRequest], None]: + r"""Return a callable for the cancel_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 "cancel_operation" not in self._stubs: + self._stubs["cancel_operation"] = self._logged_channel.unary_unary( + "/google.longrunning.Operations/CancelOperation", + request_serializer=operations_pb2.CancelOperationRequest.SerializeToString, + response_deserializer=None, + ) + return self._stubs["cancel_operation"] + + @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._logged_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._logged_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__ = ("RuleExecutionErrorServiceGrpcTransport",) diff --git a/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_execution_error_service/transports/grpc_asyncio.py b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_execution_error_service/transports/grpc_asyncio.py new file mode 100644 index 000000000000..1768420165a4 --- /dev/null +++ b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_execution_error_service/transports/grpc_asyncio.py @@ -0,0 +1,491 @@ +# -*- coding: utf-8 -*- +# Copyright 2026 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 inspect +import json +import logging as std_logging +import pickle +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +import google.protobuf.message +import grpc # type: ignore +import proto # type: ignore +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1, grpc_helpers_async +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.longrunning import operations_pb2 # type: ignore +from google.protobuf.json_format import MessageToJson +from grpc.experimental import aio # type: ignore + +from google.cloud.chronicle_v1.types import rule_execution_error + +from .base import DEFAULT_CLIENT_INFO, RuleExecutionErrorServiceTransport +from .grpc import RuleExecutionErrorServiceGrpcTransport + +try: + from google.api_core import client_logging # type: ignore + + CLIENT_LOGGING_SUPPORTED = True # pragma: NO COVER +except ImportError: # pragma: NO COVER + CLIENT_LOGGING_SUPPORTED = False + +_LOGGER = std_logging.getLogger(__name__) + + +class _LoggingClientAIOInterceptor( + grpc.aio.UnaryUnaryClientInterceptor +): # pragma: NO COVER + async def intercept_unary_unary(self, continuation, client_call_details, request): + logging_enabled = CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + std_logging.DEBUG + ) + if logging_enabled: # pragma: NO COVER + request_metadata = client_call_details.metadata + if isinstance(request, proto.Message): + request_payload = type(request).to_json(request) + elif isinstance(request, google.protobuf.message.Message): + request_payload = MessageToJson(request) + else: + request_payload = f"{type(request).__name__}: {pickle.dumps(request)!r}" + + request_metadata = { + key: value.decode("utf-8") if isinstance(value, bytes) else value + for key, value in request_metadata + } + grpc_request = { + "payload": request_payload, + "requestMethod": "grpc", + "metadata": dict(request_metadata), + } + _LOGGER.debug( + f"Sending request for {client_call_details.method}", + extra={ + "serviceName": "google.cloud.chronicle.v1.RuleExecutionErrorService", + "rpcName": str(client_call_details.method), + "request": grpc_request, + "metadata": grpc_request["metadata"], + }, + ) + response = await continuation(client_call_details, request) + if logging_enabled: # pragma: NO COVER + response_metadata = await response.trailing_metadata() + # Convert gRPC metadata `` to list of tuples + metadata = ( + dict([(k, str(v)) for k, v in response_metadata]) + if response_metadata + else None + ) + result = await response + if isinstance(result, proto.Message): + response_payload = type(result).to_json(result) + elif isinstance(result, google.protobuf.message.Message): + response_payload = MessageToJson(result) + else: + response_payload = f"{type(result).__name__}: {pickle.dumps(result)!r}" + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.cloud.chronicle.v1.RuleExecutionErrorService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class RuleExecutionErrorServiceGrpcAsyncIOTransport(RuleExecutionErrorServiceTransport): + """gRPC AsyncIO backend transport for RuleExecutionErrorService. + + RuleExecutionErrorService contains endpoints related to rule + execution errors. + + 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 = "chronicle.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]): Deprecated. A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. This argument will be + removed in the next major version of this library. + 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 = "chronicle.googleapis.com", + credentials: Optional[ga_credentials.Credentials] = None, + credentials_file: Optional[str] = None, + scopes: Optional[Sequence[str]] = None, + channel: Optional[Union[aio.Channel, Callable[..., aio.Channel]]] = None, + api_mtls_endpoint: Optional[str] = None, + client_cert_source: Optional[Callable[[], Tuple[bytes, bytes]]] = None, + ssl_channel_credentials: Optional[grpc.ChannelCredentials] = None, + client_cert_source_for_mtls: Optional[Callable[[], Tuple[bytes, bytes]]] = None, + quota_project_id: Optional[str] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, + api_audience: Optional[str] = None, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to (default: 'chronicle.googleapis.com'). + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + This argument is ignored if a ``channel`` instance is provided. + credentials_file (Optional[str]): Deprecated. A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if a ``channel`` instance is provided. + This argument will be removed in the next major version of this library. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + channel (Optional[Union[aio.Channel, Callable[..., aio.Channel]]]): + A ``Channel`` instance through which to make calls, or a Callable + that constructs and returns one. If set to None, ``self.create_channel`` + is used to create the channel. If a Callable is given, it will be called + with the same arguments as used in ``self.create_channel``. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if a ``channel`` instance is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if a ``channel`` instance or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + api_audience (Optional[str]): The intended audience for the API calls + to the service that will be set when using certain 3rd party + authentication flows. Audience is typically a resource identifier. + If not set, the host value will be used as a default. + + Raises: + google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn("client_cert_source is deprecated", DeprecationWarning) + + if isinstance(channel, aio.Channel): + # Ignore credentials if a channel was passed. + credentials = None + self._ignore_credentials = True + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + else: + self._ssl_channel_credentials = SslCredentials().ssl_credentials + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + api_audience=api_audience, + ) + + if not self._grpc_channel: + # initialize with the provided callable or the default channel + channel_init = channel or type(self).create_channel + self._grpc_channel = channel_init( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + self._interceptor = _LoggingClientAIOInterceptor() + self._grpc_channel._unary_unary_interceptors.append(self._interceptor) + self._logged_channel = self._grpc_channel + self._wrap_with_kind = ( + "kind" in inspect.signature(gapic_v1.method_async.wrap_method).parameters + ) + # Wrap messages. This must be done after self._logged_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 list_rule_execution_errors( + self, + ) -> Callable[ + [rule_execution_error.ListRuleExecutionErrorsRequest], + Awaitable[rule_execution_error.ListRuleExecutionErrorsResponse], + ]: + r"""Return a callable for the list rule execution errors method over gRPC. + + Lists rule execution errors. + + Returns: + Callable[[~.ListRuleExecutionErrorsRequest], + Awaitable[~.ListRuleExecutionErrorsResponse]]: + 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_rule_execution_errors" not in self._stubs: + self._stubs["list_rule_execution_errors"] = ( + self._logged_channel.unary_unary( + "/google.cloud.chronicle.v1.RuleExecutionErrorService/ListRuleExecutionErrors", + request_serializer=rule_execution_error.ListRuleExecutionErrorsRequest.serialize, + response_deserializer=rule_execution_error.ListRuleExecutionErrorsResponse.deserialize, + ) + ) + return self._stubs["list_rule_execution_errors"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.list_rule_execution_errors: self._wrap_method( + self.list_rule_execution_errors, + default_retry=retries.AsyncRetry( + initial=1.0, + maximum=600.0, + multiplier=1.3, + predicate=retries.if_exception_type( + core_exceptions.ServiceUnavailable, + ), + deadline=600.0, + ), + default_timeout=600.0, + client_info=client_info, + ), + self.cancel_operation: self._wrap_method( + self.cancel_operation, + default_timeout=None, + client_info=client_info, + ), + self.delete_operation: self._wrap_method( + self.delete_operation, + default_timeout=None, + client_info=client_info, + ), + self.get_operation: self._wrap_method( + self.get_operation, + default_timeout=None, + client_info=client_info, + ), + self.list_operations: self._wrap_method( + self.list_operations, + default_timeout=None, + client_info=client_info, + ), + } + + def _wrap_method(self, func, *args, **kwargs): + if self._wrap_with_kind: # pragma: NO COVER + kwargs["kind"] = self.kind + return gapic_v1.method_async.wrap_method(func, *args, **kwargs) + + def close(self): + return self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc_asyncio" + + @property + def delete_operation( + self, + ) -> Callable[[operations_pb2.DeleteOperationRequest], None]: + r"""Return a callable for the delete_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 "delete_operation" not in self._stubs: + self._stubs["delete_operation"] = self._logged_channel.unary_unary( + "/google.longrunning.Operations/DeleteOperation", + request_serializer=operations_pb2.DeleteOperationRequest.SerializeToString, + response_deserializer=None, + ) + return self._stubs["delete_operation"] + + @property + def cancel_operation( + self, + ) -> Callable[[operations_pb2.CancelOperationRequest], None]: + r"""Return a callable for the cancel_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 "cancel_operation" not in self._stubs: + self._stubs["cancel_operation"] = self._logged_channel.unary_unary( + "/google.longrunning.Operations/CancelOperation", + request_serializer=operations_pb2.CancelOperationRequest.SerializeToString, + response_deserializer=None, + ) + return self._stubs["cancel_operation"] + + @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._logged_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._logged_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__ = ("RuleExecutionErrorServiceGrpcAsyncIOTransport",) diff --git a/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_execution_error_service/transports/rest.py b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_execution_error_service/transports/rest.py new file mode 100644 index 000000000000..bf91cfbaf6c3 --- /dev/null +++ b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_execution_error_service/transports/rest.py @@ -0,0 +1,1029 @@ +# -*- coding: utf-8 -*- +# Copyright 2026 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 logging +import warnings +from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple, Union + +import google.protobuf +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1, rest_helpers, rest_streaming +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.requests import AuthorizedSession # type: ignore +from google.longrunning import operations_pb2 # type: ignore +from google.protobuf import json_format +from requests import __version__ as requests_version + +from google.cloud.chronicle_v1.types import rule_execution_error + +from .base import DEFAULT_CLIENT_INFO as BASE_DEFAULT_CLIENT_INFO +from .rest_base import _BaseRuleExecutionErrorServiceRestTransport + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault, None] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object, None] # type: ignore + +try: + from google.api_core import client_logging # type: ignore + + CLIENT_LOGGING_SUPPORTED = True # pragma: NO COVER +except ImportError: # pragma: NO COVER + CLIENT_LOGGING_SUPPORTED = False + +_LOGGER = logging.getLogger(__name__) + +DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=BASE_DEFAULT_CLIENT_INFO.gapic_version, + grpc_version=None, + rest_version=f"requests@{requests_version}", +) + +if hasattr(DEFAULT_CLIENT_INFO, "protobuf_runtime_version"): # pragma: NO COVER + DEFAULT_CLIENT_INFO.protobuf_runtime_version = google.protobuf.__version__ + + +class RuleExecutionErrorServiceRestInterceptor: + """Interceptor for RuleExecutionErrorService. + + 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 RuleExecutionErrorServiceRestTransport. + + .. code-block:: python + class MyCustomRuleExecutionErrorServiceInterceptor(RuleExecutionErrorServiceRestInterceptor): + def pre_list_rule_execution_errors(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_list_rule_execution_errors(self, response): + logging.log(f"Received response: {response}") + return response + + transport = RuleExecutionErrorServiceRestTransport(interceptor=MyCustomRuleExecutionErrorServiceInterceptor()) + client = RuleExecutionErrorServiceClient(transport=transport) + + + """ + + def pre_list_rule_execution_errors( + self, + request: rule_execution_error.ListRuleExecutionErrorsRequest, + metadata: Sequence[Tuple[str, Union[str, bytes]]], + ) -> Tuple[ + rule_execution_error.ListRuleExecutionErrorsRequest, + Sequence[Tuple[str, Union[str, bytes]]], + ]: + """Pre-rpc interceptor for list_rule_execution_errors + + Override in a subclass to manipulate the request or metadata + before they are sent to the RuleExecutionErrorService server. + """ + return request, metadata + + def post_list_rule_execution_errors( + self, response: rule_execution_error.ListRuleExecutionErrorsResponse + ) -> rule_execution_error.ListRuleExecutionErrorsResponse: + """Post-rpc interceptor for list_rule_execution_errors + + DEPRECATED. Please use the `post_list_rule_execution_errors_with_metadata` + interceptor instead. + + Override in a subclass to read or manipulate the response + after it is returned by the RuleExecutionErrorService server but before + it is returned to user code. This `post_list_rule_execution_errors` interceptor runs + before the `post_list_rule_execution_errors_with_metadata` interceptor. + """ + return response + + def post_list_rule_execution_errors_with_metadata( + self, + response: rule_execution_error.ListRuleExecutionErrorsResponse, + metadata: Sequence[Tuple[str, Union[str, bytes]]], + ) -> Tuple[ + rule_execution_error.ListRuleExecutionErrorsResponse, + Sequence[Tuple[str, Union[str, bytes]]], + ]: + """Post-rpc interceptor for list_rule_execution_errors + + Override in a subclass to read or manipulate the response or metadata after it + is returned by the RuleExecutionErrorService server but before it is returned to user code. + + We recommend only using this `post_list_rule_execution_errors_with_metadata` + interceptor in new development instead of the `post_list_rule_execution_errors` interceptor. + When both interceptors are used, this `post_list_rule_execution_errors_with_metadata` interceptor runs after the + `post_list_rule_execution_errors` interceptor. The (possibly modified) response returned by + `post_list_rule_execution_errors` will be passed to + `post_list_rule_execution_errors_with_metadata`. + """ + return response, metadata + + def pre_cancel_operation( + self, + request: operations_pb2.CancelOperationRequest, + metadata: Sequence[Tuple[str, Union[str, bytes]]], + ) -> Tuple[ + operations_pb2.CancelOperationRequest, Sequence[Tuple[str, Union[str, bytes]]] + ]: + """Pre-rpc interceptor for cancel_operation + + Override in a subclass to manipulate the request or metadata + before they are sent to the RuleExecutionErrorService server. + """ + return request, metadata + + def post_cancel_operation(self, response: None) -> None: + """Post-rpc interceptor for cancel_operation + + Override in a subclass to manipulate the response + after it is returned by the RuleExecutionErrorService server but before + it is returned to user code. + """ + return response + + def pre_delete_operation( + self, + request: operations_pb2.DeleteOperationRequest, + metadata: Sequence[Tuple[str, Union[str, bytes]]], + ) -> Tuple[ + operations_pb2.DeleteOperationRequest, Sequence[Tuple[str, Union[str, bytes]]] + ]: + """Pre-rpc interceptor for delete_operation + + Override in a subclass to manipulate the request or metadata + before they are sent to the RuleExecutionErrorService server. + """ + return request, metadata + + def post_delete_operation(self, response: None) -> None: + """Post-rpc interceptor for delete_operation + + Override in a subclass to manipulate the response + after it is returned by the RuleExecutionErrorService server but before + it is returned to user code. + """ + return response + + def pre_get_operation( + self, + request: operations_pb2.GetOperationRequest, + metadata: Sequence[Tuple[str, Union[str, bytes]]], + ) -> Tuple[ + operations_pb2.GetOperationRequest, Sequence[Tuple[str, Union[str, bytes]]] + ]: + """Pre-rpc interceptor for get_operation + + Override in a subclass to manipulate the request or metadata + before they are sent to the RuleExecutionErrorService 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 RuleExecutionErrorService server but before + it is returned to user code. + """ + return response + + def pre_list_operations( + self, + request: operations_pb2.ListOperationsRequest, + metadata: Sequence[Tuple[str, Union[str, bytes]]], + ) -> Tuple[ + operations_pb2.ListOperationsRequest, Sequence[Tuple[str, Union[str, bytes]]] + ]: + """Pre-rpc interceptor for list_operations + + Override in a subclass to manipulate the request or metadata + before they are sent to the RuleExecutionErrorService 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 RuleExecutionErrorService server but before + it is returned to user code. + """ + return response + + +@dataclasses.dataclass +class RuleExecutionErrorServiceRestStub: + _session: AuthorizedSession + _host: str + _interceptor: RuleExecutionErrorServiceRestInterceptor + + +class RuleExecutionErrorServiceRestTransport( + _BaseRuleExecutionErrorServiceRestTransport +): + """REST backend synchronous transport for RuleExecutionErrorService. + + RuleExecutionErrorService contains endpoints related to rule + execution errors. + + 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 = "chronicle.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[RuleExecutionErrorServiceRestInterceptor] = None, + api_audience: Optional[str] = None, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to (default: 'chronicle.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]): Deprecated. A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. This argument will be + removed in the next major version of this library. + 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. + interceptor (Optional[RuleExecutionErrorServiceRestInterceptor]): Interceptor used + to manipulate requests, request metadata, and responses. + api_audience (Optional[str]): The intended audience for the API calls + to the service that will be set when using certain 3rd party + authentication flows. Audience is typically a resource identifier. + If not set, the host value will be used as a default. + """ + # 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 + super().__init__( + host=host, + credentials=credentials, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + url_scheme=url_scheme, + 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 RuleExecutionErrorServiceRestInterceptor() + self._prep_wrapped_messages(client_info) + + class _ListRuleExecutionErrors( + _BaseRuleExecutionErrorServiceRestTransport._BaseListRuleExecutionErrors, + RuleExecutionErrorServiceRestStub, + ): + def __hash__(self): + return hash( + "RuleExecutionErrorServiceRestTransport.ListRuleExecutionErrors" + ) + + @staticmethod + def _get_response( + host, + metadata, + query_params, + session, + timeout, + transcoded_request, + body=None, + ): + uri = transcoded_request["uri"] + method = transcoded_request["method"] + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(session, method)( + "{host}{uri}".format(host=host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + ) + return response + + def __call__( + self, + request: rule_execution_error.ListRuleExecutionErrorsRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> rule_execution_error.ListRuleExecutionErrorsResponse: + r"""Call the list rule execution + errors method over HTTP. + + Args: + request (~.rule_execution_error.ListRuleExecutionErrorsRequest): + The request object. Request message for + ListRuleExecutionErrors. + 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + ~.rule_execution_error.ListRuleExecutionErrorsResponse: + Response message for + ListRuleExecutionErrors. + + """ + + http_options = _BaseRuleExecutionErrorServiceRestTransport._BaseListRuleExecutionErrors._get_http_options() + + request, metadata = self._interceptor.pre_list_rule_execution_errors( + request, metadata + ) + transcoded_request = _BaseRuleExecutionErrorServiceRestTransport._BaseListRuleExecutionErrors._get_transcoded_request( + http_options, request + ) + + # Jsonify the query params + query_params = _BaseRuleExecutionErrorServiceRestTransport._BaseListRuleExecutionErrors._get_query_params_json( + transcoded_request + ) + + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + logging.DEBUG + ): # pragma: NO COVER + request_url = "{host}{uri}".format( + host=self._host, uri=transcoded_request["uri"] + ) + method = transcoded_request["method"] + try: + request_payload = type(request).to_json(request) + except: + request_payload = None + http_request = { + "payload": request_payload, + "requestMethod": method, + "requestUrl": request_url, + "headers": dict(metadata), + } + _LOGGER.debug( + f"Sending request for google.cloud.chronicle_v1.RuleExecutionErrorServiceClient.ListRuleExecutionErrors", + extra={ + "serviceName": "google.cloud.chronicle.v1.RuleExecutionErrorService", + "rpcName": "ListRuleExecutionErrors", + "httpRequest": http_request, + "metadata": http_request["headers"], + }, + ) + + # Send the request + response = RuleExecutionErrorServiceRestTransport._ListRuleExecutionErrors._get_response( + self._host, + metadata, + query_params, + self._session, + timeout, + transcoded_request, + ) + + # 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 = rule_execution_error.ListRuleExecutionErrorsResponse() + pb_resp = rule_execution_error.ListRuleExecutionErrorsResponse.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + + resp = self._interceptor.post_list_rule_execution_errors(resp) + response_metadata = [(k, str(v)) for k, v in response.headers.items()] + resp, _ = self._interceptor.post_list_rule_execution_errors_with_metadata( + resp, response_metadata + ) + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + logging.DEBUG + ): # pragma: NO COVER + try: + response_payload = ( + rule_execution_error.ListRuleExecutionErrorsResponse.to_json( + response + ) + ) + except: + response_payload = None + http_response = { + "payload": response_payload, + "headers": dict(response.headers), + "status": response.status_code, + } + _LOGGER.debug( + "Received response for google.cloud.chronicle_v1.RuleExecutionErrorServiceClient.list_rule_execution_errors", + extra={ + "serviceName": "google.cloud.chronicle.v1.RuleExecutionErrorService", + "rpcName": "ListRuleExecutionErrors", + "metadata": http_response["headers"], + "httpResponse": http_response, + }, + ) + return resp + + @property + def list_rule_execution_errors( + self, + ) -> Callable[ + [rule_execution_error.ListRuleExecutionErrorsRequest], + rule_execution_error.ListRuleExecutionErrorsResponse, + ]: + # 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._ListRuleExecutionErrors( + self._session, self._host, self._interceptor + ) # type: ignore + + @property + def cancel_operation(self): + return self._CancelOperation(self._session, self._host, self._interceptor) # type: ignore + + class _CancelOperation( + _BaseRuleExecutionErrorServiceRestTransport._BaseCancelOperation, + RuleExecutionErrorServiceRestStub, + ): + def __hash__(self): + return hash("RuleExecutionErrorServiceRestTransport.CancelOperation") + + @staticmethod + def _get_response( + host, + metadata, + query_params, + session, + timeout, + transcoded_request, + body=None, + ): + uri = transcoded_request["uri"] + method = transcoded_request["method"] + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(session, method)( + "{host}{uri}".format(host=host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + data=body, + ) + return response + + def __call__( + self, + request: operations_pb2.CancelOperationRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> None: + r"""Call the cancel operation method over HTTP. + + Args: + request (operations_pb2.CancelOperationRequest): + The request object for CancelOperation 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + """ + + http_options = _BaseRuleExecutionErrorServiceRestTransport._BaseCancelOperation._get_http_options() + + request, metadata = self._interceptor.pre_cancel_operation( + request, metadata + ) + transcoded_request = _BaseRuleExecutionErrorServiceRestTransport._BaseCancelOperation._get_transcoded_request( + http_options, request + ) + + body = _BaseRuleExecutionErrorServiceRestTransport._BaseCancelOperation._get_request_body_json( + transcoded_request + ) + + # Jsonify the query params + query_params = _BaseRuleExecutionErrorServiceRestTransport._BaseCancelOperation._get_query_params_json( + transcoded_request + ) + + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + logging.DEBUG + ): # pragma: NO COVER + request_url = "{host}{uri}".format( + host=self._host, uri=transcoded_request["uri"] + ) + method = transcoded_request["method"] + try: + request_payload = json_format.MessageToJson(request) + except: + request_payload = None + http_request = { + "payload": request_payload, + "requestMethod": method, + "requestUrl": request_url, + "headers": dict(metadata), + } + _LOGGER.debug( + f"Sending request for google.cloud.chronicle_v1.RuleExecutionErrorServiceClient.CancelOperation", + extra={ + "serviceName": "google.cloud.chronicle.v1.RuleExecutionErrorService", + "rpcName": "CancelOperation", + "httpRequest": http_request, + "metadata": http_request["headers"], + }, + ) + + # Send the request + response = ( + RuleExecutionErrorServiceRestTransport._CancelOperation._get_response( + self._host, + metadata, + query_params, + self._session, + timeout, + transcoded_request, + 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 self._interceptor.post_cancel_operation(None) + + @property + def delete_operation(self): + return self._DeleteOperation(self._session, self._host, self._interceptor) # type: ignore + + class _DeleteOperation( + _BaseRuleExecutionErrorServiceRestTransport._BaseDeleteOperation, + RuleExecutionErrorServiceRestStub, + ): + def __hash__(self): + return hash("RuleExecutionErrorServiceRestTransport.DeleteOperation") + + @staticmethod + def _get_response( + host, + metadata, + query_params, + session, + timeout, + transcoded_request, + body=None, + ): + uri = transcoded_request["uri"] + method = transcoded_request["method"] + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(session, method)( + "{host}{uri}".format(host=host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + ) + return response + + def __call__( + self, + request: operations_pb2.DeleteOperationRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> None: + r"""Call the delete operation method over HTTP. + + Args: + request (operations_pb2.DeleteOperationRequest): + The request object for DeleteOperation 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + """ + + http_options = _BaseRuleExecutionErrorServiceRestTransport._BaseDeleteOperation._get_http_options() + + request, metadata = self._interceptor.pre_delete_operation( + request, metadata + ) + transcoded_request = _BaseRuleExecutionErrorServiceRestTransport._BaseDeleteOperation._get_transcoded_request( + http_options, request + ) + + # Jsonify the query params + query_params = _BaseRuleExecutionErrorServiceRestTransport._BaseDeleteOperation._get_query_params_json( + transcoded_request + ) + + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + logging.DEBUG + ): # pragma: NO COVER + request_url = "{host}{uri}".format( + host=self._host, uri=transcoded_request["uri"] + ) + method = transcoded_request["method"] + try: + request_payload = json_format.MessageToJson(request) + except: + request_payload = None + http_request = { + "payload": request_payload, + "requestMethod": method, + "requestUrl": request_url, + "headers": dict(metadata), + } + _LOGGER.debug( + f"Sending request for google.cloud.chronicle_v1.RuleExecutionErrorServiceClient.DeleteOperation", + extra={ + "serviceName": "google.cloud.chronicle.v1.RuleExecutionErrorService", + "rpcName": "DeleteOperation", + "httpRequest": http_request, + "metadata": http_request["headers"], + }, + ) + + # Send the request + response = ( + RuleExecutionErrorServiceRestTransport._DeleteOperation._get_response( + self._host, + metadata, + query_params, + self._session, + timeout, + transcoded_request, + ) + ) + + # 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 self._interceptor.post_delete_operation(None) + + @property + def get_operation(self): + return self._GetOperation(self._session, self._host, self._interceptor) # type: ignore + + class _GetOperation( + _BaseRuleExecutionErrorServiceRestTransport._BaseGetOperation, + RuleExecutionErrorServiceRestStub, + ): + def __hash__(self): + return hash("RuleExecutionErrorServiceRestTransport.GetOperation") + + @staticmethod + def _get_response( + host, + metadata, + query_params, + session, + timeout, + transcoded_request, + body=None, + ): + uri = transcoded_request["uri"] + method = transcoded_request["method"] + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(session, method)( + "{host}{uri}".format(host=host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + ) + return response + + def __call__( + self, + request: operations_pb2.GetOperationRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + operations_pb2.Operation: Response from GetOperation method. + """ + + http_options = _BaseRuleExecutionErrorServiceRestTransport._BaseGetOperation._get_http_options() + + request, metadata = self._interceptor.pre_get_operation(request, metadata) + transcoded_request = _BaseRuleExecutionErrorServiceRestTransport._BaseGetOperation._get_transcoded_request( + http_options, request + ) + + # Jsonify the query params + query_params = _BaseRuleExecutionErrorServiceRestTransport._BaseGetOperation._get_query_params_json( + transcoded_request + ) + + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + logging.DEBUG + ): # pragma: NO COVER + request_url = "{host}{uri}".format( + host=self._host, uri=transcoded_request["uri"] + ) + method = transcoded_request["method"] + try: + request_payload = json_format.MessageToJson(request) + except: + request_payload = None + http_request = { + "payload": request_payload, + "requestMethod": method, + "requestUrl": request_url, + "headers": dict(metadata), + } + _LOGGER.debug( + f"Sending request for google.cloud.chronicle_v1.RuleExecutionErrorServiceClient.GetOperation", + extra={ + "serviceName": "google.cloud.chronicle.v1.RuleExecutionErrorService", + "rpcName": "GetOperation", + "httpRequest": http_request, + "metadata": http_request["headers"], + }, + ) + + # Send the request + response = ( + RuleExecutionErrorServiceRestTransport._GetOperation._get_response( + self._host, + metadata, + query_params, + self._session, + timeout, + transcoded_request, + ) + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + content = response.content.decode("utf-8") + resp = operations_pb2.Operation() + resp = json_format.Parse(content, resp) + resp = self._interceptor.post_get_operation(resp) + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + logging.DEBUG + ): # pragma: NO COVER + try: + response_payload = json_format.MessageToJson(resp) + except: + response_payload = None + http_response = { + "payload": response_payload, + "headers": dict(response.headers), + "status": response.status_code, + } + _LOGGER.debug( + "Received response for google.cloud.chronicle_v1.RuleExecutionErrorServiceAsyncClient.GetOperation", + extra={ + "serviceName": "google.cloud.chronicle.v1.RuleExecutionErrorService", + "rpcName": "GetOperation", + "httpResponse": http_response, + "metadata": http_response["headers"], + }, + ) + return resp + + @property + def list_operations(self): + return self._ListOperations(self._session, self._host, self._interceptor) # type: ignore + + class _ListOperations( + _BaseRuleExecutionErrorServiceRestTransport._BaseListOperations, + RuleExecutionErrorServiceRestStub, + ): + def __hash__(self): + return hash("RuleExecutionErrorServiceRestTransport.ListOperations") + + @staticmethod + def _get_response( + host, + metadata, + query_params, + session, + timeout, + transcoded_request, + body=None, + ): + uri = transcoded_request["uri"] + method = transcoded_request["method"] + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(session, method)( + "{host}{uri}".format(host=host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + ) + return response + + def __call__( + self, + request: operations_pb2.ListOperationsRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + operations_pb2.ListOperationsResponse: Response from ListOperations method. + """ + + http_options = _BaseRuleExecutionErrorServiceRestTransport._BaseListOperations._get_http_options() + + request, metadata = self._interceptor.pre_list_operations(request, metadata) + transcoded_request = _BaseRuleExecutionErrorServiceRestTransport._BaseListOperations._get_transcoded_request( + http_options, request + ) + + # Jsonify the query params + query_params = _BaseRuleExecutionErrorServiceRestTransport._BaseListOperations._get_query_params_json( + transcoded_request + ) + + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + logging.DEBUG + ): # pragma: NO COVER + request_url = "{host}{uri}".format( + host=self._host, uri=transcoded_request["uri"] + ) + method = transcoded_request["method"] + try: + request_payload = json_format.MessageToJson(request) + except: + request_payload = None + http_request = { + "payload": request_payload, + "requestMethod": method, + "requestUrl": request_url, + "headers": dict(metadata), + } + _LOGGER.debug( + f"Sending request for google.cloud.chronicle_v1.RuleExecutionErrorServiceClient.ListOperations", + extra={ + "serviceName": "google.cloud.chronicle.v1.RuleExecutionErrorService", + "rpcName": "ListOperations", + "httpRequest": http_request, + "metadata": http_request["headers"], + }, + ) + + # Send the request + response = ( + RuleExecutionErrorServiceRestTransport._ListOperations._get_response( + self._host, + metadata, + query_params, + self._session, + timeout, + transcoded_request, + ) + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + content = response.content.decode("utf-8") + resp = operations_pb2.ListOperationsResponse() + resp = json_format.Parse(content, resp) + resp = self._interceptor.post_list_operations(resp) + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + logging.DEBUG + ): # pragma: NO COVER + try: + response_payload = json_format.MessageToJson(resp) + except: + response_payload = None + http_response = { + "payload": response_payload, + "headers": dict(response.headers), + "status": response.status_code, + } + _LOGGER.debug( + "Received response for google.cloud.chronicle_v1.RuleExecutionErrorServiceAsyncClient.ListOperations", + extra={ + "serviceName": "google.cloud.chronicle.v1.RuleExecutionErrorService", + "rpcName": "ListOperations", + "httpResponse": http_response, + "metadata": http_response["headers"], + }, + ) + return resp + + @property + def kind(self) -> str: + return "rest" + + def close(self): + self._session.close() + + +__all__ = ("RuleExecutionErrorServiceRestTransport",) diff --git a/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_execution_error_service/transports/rest_base.py b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_execution_error_service/transports/rest_base.py new file mode 100644 index 000000000000..5682fe7b9304 --- /dev/null +++ b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_execution_error_service/transports/rest_base.py @@ -0,0 +1,245 @@ +# -*- coding: utf-8 -*- +# Copyright 2026 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 json # type: ignore +import re +from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1, path_template +from google.longrunning import operations_pb2 # type: ignore +from google.protobuf import json_format + +from google.cloud.chronicle_v1.types import rule_execution_error + +from .base import DEFAULT_CLIENT_INFO, RuleExecutionErrorServiceTransport + + +class _BaseRuleExecutionErrorServiceRestTransport(RuleExecutionErrorServiceTransport): + """Base REST backend transport for RuleExecutionErrorService. + + Note: This class is not meant to be used directly. Use its sync and + async sub-classes instead. + + 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 = "chronicle.googleapis.com", + credentials: Optional[Any] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, + url_scheme: str = "https", + api_audience: Optional[str] = None, + ) -> None: + """Instantiate the transport. + Args: + host (Optional[str]): + The hostname to connect to (default: 'chronicle.googleapis.com'). + credentials (Optional[Any]): 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. + 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 + 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, + ) + + class _BaseListRuleExecutionErrors: + def __hash__(self): # pragma: NO COVER + return NotImplementedError("__hash__ must be implemented.") + + __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 + } + + @staticmethod + def _get_http_options(): + http_options: List[Dict[str, str]] = [ + { + "method": "get", + "uri": "/v1/{parent=projects/*/locations/*/instances/*}/ruleExecutionErrors", + }, + ] + return http_options + + @staticmethod + def _get_transcoded_request(http_options, request): + pb_request = rule_execution_error.ListRuleExecutionErrorsRequest.pb(request) + transcoded_request = path_template.transcode(http_options, pb_request) + return transcoded_request + + @staticmethod + def _get_query_params_json(transcoded_request): + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + use_integers_for_enums=True, + ) + ) + query_params.update( + _BaseRuleExecutionErrorServiceRestTransport._BaseListRuleExecutionErrors._get_unset_required_fields( + query_params + ) + ) + + query_params["$alt"] = "json;enum-encoding=int" + return query_params + + class _BaseCancelOperation: + def __hash__(self): # pragma: NO COVER + return NotImplementedError("__hash__ must be implemented.") + + @staticmethod + def _get_http_options(): + http_options: List[Dict[str, str]] = [ + { + "method": "post", + "uri": "/v1/{name=projects/*/locations/*/instances/*/operations/*}:cancel", + "body": "*", + }, + ] + return http_options + + @staticmethod + def _get_transcoded_request(http_options, request): + request_kwargs = json_format.MessageToDict(request) + transcoded_request = path_template.transcode(http_options, **request_kwargs) + return transcoded_request + + @staticmethod + def _get_request_body_json(transcoded_request): + body = json.dumps(transcoded_request["body"]) + return body + + @staticmethod + def _get_query_params_json(transcoded_request): + query_params = json.loads(json.dumps(transcoded_request["query_params"])) + return query_params + + class _BaseDeleteOperation: + def __hash__(self): # pragma: NO COVER + return NotImplementedError("__hash__ must be implemented.") + + @staticmethod + def _get_http_options(): + http_options: List[Dict[str, str]] = [ + { + "method": "delete", + "uri": "/v1/{name=projects/*/locations/*/instances/*/operations/*}", + }, + ] + return http_options + + @staticmethod + def _get_transcoded_request(http_options, request): + request_kwargs = json_format.MessageToDict(request) + transcoded_request = path_template.transcode(http_options, **request_kwargs) + return transcoded_request + + @staticmethod + def _get_query_params_json(transcoded_request): + query_params = json.loads(json.dumps(transcoded_request["query_params"])) + return query_params + + class _BaseGetOperation: + def __hash__(self): # pragma: NO COVER + return NotImplementedError("__hash__ must be implemented.") + + @staticmethod + def _get_http_options(): + http_options: List[Dict[str, str]] = [ + { + "method": "get", + "uri": "/v1/{name=projects/*/locations/*/instances/*/operations/*}", + }, + ] + return http_options + + @staticmethod + def _get_transcoded_request(http_options, request): + request_kwargs = json_format.MessageToDict(request) + transcoded_request = path_template.transcode(http_options, **request_kwargs) + return transcoded_request + + @staticmethod + def _get_query_params_json(transcoded_request): + query_params = json.loads(json.dumps(transcoded_request["query_params"])) + return query_params + + class _BaseListOperations: + def __hash__(self): # pragma: NO COVER + return NotImplementedError("__hash__ must be implemented.") + + @staticmethod + def _get_http_options(): + http_options: List[Dict[str, str]] = [ + { + "method": "get", + "uri": "/v1/{name=projects/*/locations/*/instances/*}/operations", + }, + ] + return http_options + + @staticmethod + def _get_transcoded_request(http_options, request): + request_kwargs = json_format.MessageToDict(request) + transcoded_request = path_template.transcode(http_options, **request_kwargs) + return transcoded_request + + @staticmethod + def _get_query_params_json(transcoded_request): + query_params = json.loads(json.dumps(transcoded_request["query_params"])) + return query_params + + +__all__ = ("_BaseRuleExecutionErrorServiceRestTransport",) diff --git a/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_service/async_client.py b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_service/async_client.py index 33b8029eb468..d7944bf2de99 100644 --- a/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_service/async_client.py +++ b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_service/async_client.py @@ -85,6 +85,8 @@ class RuleServiceAsyncClient: parse_data_access_scope_path = staticmethod( RuleServiceClient.parse_data_access_scope_path ) + instance_path = staticmethod(RuleServiceClient.instance_path) + parse_instance_path = staticmethod(RuleServiceClient.parse_instance_path) reference_list_path = staticmethod(RuleServiceClient.reference_list_path) parse_reference_list_path = staticmethod( RuleServiceClient.parse_reference_list_path @@ -893,6 +895,129 @@ async def sample_delete_rule(): metadata=metadata, ) + async def verify_rule_text( + self, + request: Optional[Union[rule.VerifyRuleTextRequest, dict]] = None, + *, + instance: Optional[str] = None, + rule_text: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> rule.VerifyRuleTextResponse: + r"""Verifies the given rule text. + + .. 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 chronicle_v1 + + async def sample_verify_rule_text(): + # Create a client + client = chronicle_v1.RuleServiceAsyncClient() + + # Initialize request argument(s) + request = chronicle_v1.VerifyRuleTextRequest( + instance="instance_value", + rule_text="rule_text_value", + ) + + # Make the request + response = await client.verify_rule_text(request=request) + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.chronicle_v1.types.VerifyRuleTextRequest, dict]]): + The request object. Request message for VerifyRuleText + method. + instance (:class:`str`): + Required. The name of the parent resource, which is the + SecOps instance associated with the request. Format: + ``projects/{project}/locations/{location}/instances/{instance}`` + + This corresponds to the ``instance`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + rule_text (:class:`str`): + Required. The rule text to verify as + a UTF-8 string. + + This corresponds to the ``rule_text`` 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + google.cloud.chronicle_v1.types.VerifyRuleTextResponse: + Response message for VerifyRuleText + method. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + flattened_params = [instance, rule_text] + has_flattened_params = ( + len([param for param in flattened_params if param is not None]) > 0 + ) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, rule.VerifyRuleTextRequest): + request = rule.VerifyRuleTextRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if instance is not None: + request.instance = instance + if rule_text is not None: + request.rule_text = rule_text + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.verify_rule_text + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("instance", request.instance),)), + ) + + # 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_rule_revisions( self, request: Optional[Union[rule.ListRuleRevisionsRequest, dict]] = None, diff --git a/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_service/client.py b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_service/client.py index 6f51d7f28202..b04986aceae3 100644 --- a/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_service/client.py +++ b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_service/client.py @@ -258,6 +258,28 @@ def parse_data_access_scope_path(path: str) -> Dict[str, str]: ) return m.groupdict() if m else {} + @staticmethod + def instance_path( + project: str, + location: str, + instance: str, + ) -> str: + """Returns a fully-qualified instance string.""" + return "projects/{project}/locations/{location}/instances/{instance}".format( + project=project, + location=location, + instance=instance, + ) + + @staticmethod + def parse_instance_path(path: str) -> Dict[str, str]: + """Parses a instance path into its component segments.""" + m = re.match( + r"^projects/(?P.+?)/locations/(?P.+?)/instances/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + @staticmethod def reference_list_path( project: str, @@ -1401,6 +1423,126 @@ def sample_delete_rule(): metadata=metadata, ) + def verify_rule_text( + self, + request: Optional[Union[rule.VerifyRuleTextRequest, dict]] = None, + *, + instance: Optional[str] = None, + rule_text: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> rule.VerifyRuleTextResponse: + r"""Verifies the given rule text. + + .. 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 chronicle_v1 + + def sample_verify_rule_text(): + # Create a client + client = chronicle_v1.RuleServiceClient() + + # Initialize request argument(s) + request = chronicle_v1.VerifyRuleTextRequest( + instance="instance_value", + rule_text="rule_text_value", + ) + + # Make the request + response = client.verify_rule_text(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.chronicle_v1.types.VerifyRuleTextRequest, dict]): + The request object. Request message for VerifyRuleText + method. + instance (str): + Required. The name of the parent resource, which is the + SecOps instance associated with the request. Format: + ``projects/{project}/locations/{location}/instances/{instance}`` + + This corresponds to the ``instance`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + rule_text (str): + Required. The rule text to verify as + a UTF-8 string. + + This corresponds to the ``rule_text`` 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + google.cloud.chronicle_v1.types.VerifyRuleTextResponse: + Response message for VerifyRuleText + method. + + """ + # Create or coerce a protobuf request object. + # - Quick check: If we got a request object, we should *not* have + # gotten any keyword arguments that map to the request. + flattened_params = [instance, rule_text] + has_flattened_params = ( + len([param for param in flattened_params if param is not None]) > 0 + ) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, rule.VerifyRuleTextRequest): + request = rule.VerifyRuleTextRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if instance is not None: + request.instance = instance + if rule_text is not None: + request.rule_text = rule_text + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.verify_rule_text] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("instance", request.instance),)), + ) + + # 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_rule_revisions( self, request: Optional[Union[rule.ListRuleRevisionsRequest, dict]] = None, diff --git a/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_service/transports/base.py b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_service/transports/base.py index afeb313552d8..f157c751ee7c 100644 --- a/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_service/transports/base.py +++ b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_service/transports/base.py @@ -42,7 +42,11 @@ class RuleServiceTransport(abc.ABC): """Abstract transport class for RuleService.""" - AUTH_SCOPES = ("https://www.googleapis.com/auth/cloud-platform",) + AUTH_SCOPES = ( + "https://www.googleapis.com/auth/chronicle", + "https://www.googleapis.com/auth/chronicle.readonly", + "https://www.googleapis.com/auth/cloud-platform", + ) DEFAULT_HOST: str = "chronicle.googleapis.com" @@ -188,6 +192,20 @@ def _prep_wrapped_messages(self, client_info): default_timeout=60.0, client_info=client_info, ), + self.verify_rule_text: gapic_v1.method.wrap_method( + self.verify_rule_text, + default_retry=retries.Retry( + initial=1.0, + maximum=60.0, + multiplier=1.3, + predicate=retries.if_exception_type( + core_exceptions.ServiceUnavailable, + ), + deadline=60.0, + ), + default_timeout=60.0, + client_info=client_info, + ), self.list_rule_revisions: gapic_v1.method.wrap_method( self.list_rule_revisions, default_retry=retries.Retry( @@ -343,6 +361,15 @@ def delete_rule( ]: raise NotImplementedError() + @property + def verify_rule_text( + self, + ) -> Callable[ + [rule.VerifyRuleTextRequest], + Union[rule.VerifyRuleTextResponse, Awaitable[rule.VerifyRuleTextResponse]], + ]: + raise NotImplementedError() + @property def list_rule_revisions( self, diff --git a/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_service/transports/grpc.py b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_service/transports/grpc.py index 039364094a14..04a399a5bb83 100644 --- a/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_service/transports/grpc.py +++ b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_service/transports/grpc.py @@ -465,6 +465,32 @@ def delete_rule(self) -> Callable[[rule.DeleteRuleRequest], empty_pb2.Empty]: ) return self._stubs["delete_rule"] + @property + def verify_rule_text( + self, + ) -> Callable[[rule.VerifyRuleTextRequest], rule.VerifyRuleTextResponse]: + r"""Return a callable for the verify rule text method over gRPC. + + Verifies the given rule text. + + Returns: + Callable[[~.VerifyRuleTextRequest], + ~.VerifyRuleTextResponse]: + 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 "verify_rule_text" not in self._stubs: + self._stubs["verify_rule_text"] = self._logged_channel.unary_unary( + "/google.cloud.chronicle.v1.RuleService/VerifyRuleText", + request_serializer=rule.VerifyRuleTextRequest.serialize, + response_deserializer=rule.VerifyRuleTextResponse.deserialize, + ) + return self._stubs["verify_rule_text"] + @property def list_rule_revisions( self, diff --git a/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_service/transports/grpc_asyncio.py b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_service/transports/grpc_asyncio.py index baf85649aa48..c46853a80248 100644 --- a/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_service/transports/grpc_asyncio.py +++ b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_service/transports/grpc_asyncio.py @@ -481,6 +481,32 @@ def delete_rule( ) return self._stubs["delete_rule"] + @property + def verify_rule_text( + self, + ) -> Callable[[rule.VerifyRuleTextRequest], Awaitable[rule.VerifyRuleTextResponse]]: + r"""Return a callable for the verify rule text method over gRPC. + + Verifies the given rule text. + + Returns: + Callable[[~.VerifyRuleTextRequest], + Awaitable[~.VerifyRuleTextResponse]]: + 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 "verify_rule_text" not in self._stubs: + self._stubs["verify_rule_text"] = self._logged_channel.unary_unary( + "/google.cloud.chronicle.v1.RuleService/VerifyRuleText", + request_serializer=rule.VerifyRuleTextRequest.serialize, + response_deserializer=rule.VerifyRuleTextResponse.deserialize, + ) + return self._stubs["verify_rule_text"] + @property def list_rule_revisions( self, @@ -717,6 +743,20 @@ def _prep_wrapped_messages(self, client_info): default_timeout=60.0, client_info=client_info, ), + self.verify_rule_text: self._wrap_method( + self.verify_rule_text, + default_retry=retries.AsyncRetry( + initial=1.0, + maximum=60.0, + multiplier=1.3, + predicate=retries.if_exception_type( + core_exceptions.ServiceUnavailable, + ), + deadline=60.0, + ), + default_timeout=60.0, + client_info=client_info, + ), self.list_rule_revisions: self._wrap_method( self.list_rule_revisions, default_retry=retries.AsyncRetry( diff --git a/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_service/transports/rest.py b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_service/transports/rest.py index 208b71ec87f6..7210f17aee4d 100644 --- a/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_service/transports/rest.py +++ b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_service/transports/rest.py @@ -167,6 +167,14 @@ def post_update_rule_deployment(self, response): logging.log(f"Received response: {response}") return response + def pre_verify_rule_text(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_verify_rule_text(self, response): + logging.log(f"Received response: {response}") + return response + transport = RuleServiceRestTransport(interceptor=MyCustomRuleServiceInterceptor()) client = RuleServiceClient(transport=transport) @@ -683,6 +691,52 @@ def post_update_rule_deployment_with_metadata( """ return response, metadata + def pre_verify_rule_text( + self, + request: rule.VerifyRuleTextRequest, + metadata: Sequence[Tuple[str, Union[str, bytes]]], + ) -> Tuple[rule.VerifyRuleTextRequest, Sequence[Tuple[str, Union[str, bytes]]]]: + """Pre-rpc interceptor for verify_rule_text + + Override in a subclass to manipulate the request or metadata + before they are sent to the RuleService server. + """ + return request, metadata + + def post_verify_rule_text( + self, response: rule.VerifyRuleTextResponse + ) -> rule.VerifyRuleTextResponse: + """Post-rpc interceptor for verify_rule_text + + DEPRECATED. Please use the `post_verify_rule_text_with_metadata` + interceptor instead. + + Override in a subclass to read or manipulate the response + after it is returned by the RuleService server but before + it is returned to user code. This `post_verify_rule_text` interceptor runs + before the `post_verify_rule_text_with_metadata` interceptor. + """ + return response + + def post_verify_rule_text_with_metadata( + self, + response: rule.VerifyRuleTextResponse, + metadata: Sequence[Tuple[str, Union[str, bytes]]], + ) -> Tuple[rule.VerifyRuleTextResponse, Sequence[Tuple[str, Union[str, bytes]]]]: + """Post-rpc interceptor for verify_rule_text + + Override in a subclass to read or manipulate the response or metadata after it + is returned by the RuleService server but before it is returned to user code. + + We recommend only using this `post_verify_rule_text_with_metadata` + interceptor in new development instead of the `post_verify_rule_text` interceptor. + When both interceptors are used, this `post_verify_rule_text_with_metadata` interceptor runs after the + `post_verify_rule_text` interceptor. The (possibly modified) response returned by + `post_verify_rule_text` will be passed to + `post_verify_rule_text_with_metadata`. + """ + return response, metadata + def pre_cancel_operation( self, request: operations_pb2.CancelOperationRequest, @@ -2702,6 +2756,161 @@ def __call__( ) return resp + class _VerifyRuleText( + _BaseRuleServiceRestTransport._BaseVerifyRuleText, RuleServiceRestStub + ): + def __hash__(self): + return hash("RuleServiceRestTransport.VerifyRuleText") + + @staticmethod + def _get_response( + host, + metadata, + query_params, + session, + timeout, + transcoded_request, + body=None, + ): + uri = transcoded_request["uri"] + method = transcoded_request["method"] + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(session, method)( + "{host}{uri}".format(host=host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + data=body, + ) + return response + + def __call__( + self, + request: rule.VerifyRuleTextRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> rule.VerifyRuleTextResponse: + r"""Call the verify rule text method over HTTP. + + Args: + request (~.rule.VerifyRuleTextRequest): + The request object. Request message for VerifyRuleText + 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + ~.rule.VerifyRuleTextResponse: + Response message for VerifyRuleText + method. + + """ + + http_options = ( + _BaseRuleServiceRestTransport._BaseVerifyRuleText._get_http_options() + ) + + request, metadata = self._interceptor.pre_verify_rule_text( + request, metadata + ) + transcoded_request = _BaseRuleServiceRestTransport._BaseVerifyRuleText._get_transcoded_request( + http_options, request + ) + + body = _BaseRuleServiceRestTransport._BaseVerifyRuleText._get_request_body_json( + transcoded_request + ) + + # Jsonify the query params + query_params = _BaseRuleServiceRestTransport._BaseVerifyRuleText._get_query_params_json( + transcoded_request + ) + + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + logging.DEBUG + ): # pragma: NO COVER + request_url = "{host}{uri}".format( + host=self._host, uri=transcoded_request["uri"] + ) + method = transcoded_request["method"] + try: + request_payload = type(request).to_json(request) + except: + request_payload = None + http_request = { + "payload": request_payload, + "requestMethod": method, + "requestUrl": request_url, + "headers": dict(metadata), + } + _LOGGER.debug( + f"Sending request for google.cloud.chronicle_v1.RuleServiceClient.VerifyRuleText", + extra={ + "serviceName": "google.cloud.chronicle.v1.RuleService", + "rpcName": "VerifyRuleText", + "httpRequest": http_request, + "metadata": http_request["headers"], + }, + ) + + # Send the request + response = RuleServiceRestTransport._VerifyRuleText._get_response( + self._host, + metadata, + query_params, + self._session, + timeout, + transcoded_request, + 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 = rule.VerifyRuleTextResponse() + pb_resp = rule.VerifyRuleTextResponse.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + + resp = self._interceptor.post_verify_rule_text(resp) + response_metadata = [(k, str(v)) for k, v in response.headers.items()] + resp, _ = self._interceptor.post_verify_rule_text_with_metadata( + resp, response_metadata + ) + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + logging.DEBUG + ): # pragma: NO COVER + try: + response_payload = rule.VerifyRuleTextResponse.to_json(response) + except: + response_payload = None + http_response = { + "payload": response_payload, + "headers": dict(response.headers), + "status": response.status_code, + } + _LOGGER.debug( + "Received response for google.cloud.chronicle_v1.RuleServiceClient.verify_rule_text", + extra={ + "serviceName": "google.cloud.chronicle.v1.RuleService", + "rpcName": "VerifyRuleText", + "metadata": http_response["headers"], + "httpResponse": http_response, + }, + ) + return resp + @property def create_retrohunt( self, @@ -2786,6 +2995,14 @@ def update_rule_deployment( # In C++ this would require a dynamic_cast return self._UpdateRuleDeployment(self._session, self._host, self._interceptor) # type: ignore + @property + def verify_rule_text( + self, + ) -> Callable[[rule.VerifyRuleTextRequest], rule.VerifyRuleTextResponse]: + # 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._VerifyRuleText(self._session, self._host, self._interceptor) # type: ignore + @property def cancel_operation(self): return self._CancelOperation(self._session, self._host, self._interceptor) # type: ignore diff --git a/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_service/transports/rest_base.py b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_service/transports/rest_base.py index c5f5e9b0ff63..a95e20a79bb8 100644 --- a/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_service/transports/rest_base.py +++ b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/services/rule_service/transports/rest_base.py @@ -696,6 +696,63 @@ def _get_query_params_json(transcoded_request): query_params["$alt"] = "json;enum-encoding=int" return query_params + class _BaseVerifyRuleText: + def __hash__(self): # pragma: NO COVER + return NotImplementedError("__hash__ must be implemented.") + + __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 + } + + @staticmethod + def _get_http_options(): + http_options: List[Dict[str, str]] = [ + { + "method": "post", + "uri": "/v1/{instance=projects/*/locations/*/instances/*}:verifyRuleText", + "body": "*", + }, + ] + return http_options + + @staticmethod + def _get_transcoded_request(http_options, request): + pb_request = rule.VerifyRuleTextRequest.pb(request) + transcoded_request = path_template.transcode(http_options, pb_request) + return transcoded_request + + @staticmethod + def _get_request_body_json(transcoded_request): + # Jsonify the request body + + body = json_format.MessageToJson( + transcoded_request["body"], use_integers_for_enums=True + ) + return body + + @staticmethod + def _get_query_params_json(transcoded_request): + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + use_integers_for_enums=True, + ) + ) + query_params.update( + _BaseRuleServiceRestTransport._BaseVerifyRuleText._get_unset_required_fields( + query_params + ) + ) + + query_params["$alt"] = "json;enum-encoding=int" + return query_params + class _BaseCancelOperation: def __hash__(self): # pragma: NO COVER return NotImplementedError("__hash__ must be implemented.") diff --git a/packages/google-cloud-chronicle/google/cloud/chronicle_v1/types/__init__.py b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/types/__init__.py index dc4642a9164d..603d579ff47c 100644 --- a/packages/google-cloud-chronicle/google/cloud/chronicle_v1/types/__init__.py +++ b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/types/__init__.py @@ -171,11 +171,14 @@ ListReferenceListsResponse, ReferenceList, ReferenceListEntry, + ReferenceListError, ReferenceListScope, ReferenceListSyntaxType, ReferenceListView, ScopeInfo, UpdateReferenceListRequest, + VerifyReferenceListRequest, + VerifyReferenceListResponse, ) from .rule import ( CompilationDiagnostic, @@ -205,6 +208,13 @@ Severity, UpdateRuleDeploymentRequest, UpdateRuleRequest, + VerifyRuleTextRequest, + VerifyRuleTextResponse, +) +from .rule_execution_error import ( + ListRuleExecutionErrorsRequest, + ListRuleExecutionErrorsResponse, + RuleExecutionError, ) __all__ = ( @@ -345,9 +355,12 @@ "ListReferenceListsResponse", "ReferenceList", "ReferenceListEntry", + "ReferenceListError", "ReferenceListScope", "ScopeInfo", "UpdateReferenceListRequest", + "VerifyReferenceListRequest", + "VerifyReferenceListResponse", "ReferenceListSyntaxType", "ReferenceListView", "CompilationDiagnostic", @@ -374,7 +387,12 @@ "Severity", "UpdateRuleDeploymentRequest", "UpdateRuleRequest", + "VerifyRuleTextRequest", + "VerifyRuleTextResponse", "RuleType", "RuleView", "RunFrequency", + "ListRuleExecutionErrorsRequest", + "ListRuleExecutionErrorsResponse", + "RuleExecutionError", ) diff --git a/packages/google-cloud-chronicle/google/cloud/chronicle_v1/types/reference_list.py b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/types/reference_list.py index 3e4e377898a0..aa210783382d 100644 --- a/packages/google-cloud-chronicle/google/cloud/chronicle_v1/types/reference_list.py +++ b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/types/reference_list.py @@ -33,8 +33,11 @@ "ListReferenceListsResponse", "CreateReferenceListRequest", "UpdateReferenceListRequest", + "VerifyReferenceListRequest", + "VerifyReferenceListResponse", "ReferenceList", "ReferenceListEntry", + "ReferenceListError", }, ) @@ -282,6 +285,60 @@ class UpdateReferenceListRequest(proto.Message): ) +class VerifyReferenceListRequest(proto.Message): + r"""VerifyReferenceList request message. + + Attributes: + instance (str): + Required. The name of the parent resource, which is the + SecOps instance associated with the request. Format: + ``projects/{project}/locations/{location}/instances/{instance}`` + syntax_type (google.cloud.chronicle_v1.types.ReferenceListSyntaxType): + Required. Type (format) of list lines. + entries (MutableSequence[google.cloud.chronicle_v1.types.ReferenceListEntry]): + Required. The entries of the reference list. + Each line may be either an item in the list or a + comment. + """ + + instance: str = proto.Field( + proto.STRING, + number=1, + ) + syntax_type: "ReferenceListSyntaxType" = proto.Field( + proto.ENUM, + number=2, + enum="ReferenceListSyntaxType", + ) + entries: MutableSequence["ReferenceListEntry"] = proto.RepeatedField( + proto.MESSAGE, + number=3, + message="ReferenceListEntry", + ) + + +class VerifyReferenceListResponse(proto.Message): + r"""VerifyListResponse response message. + + Attributes: + success (bool): + Validity of list - true if no errors found. + errors (MutableSequence[google.cloud.chronicle_v1.types.ReferenceListError]): + Line-level errors causing the list to be + invalid. + """ + + success: bool = proto.Field( + proto.BOOL, + number=1, + ) + errors: MutableSequence["ReferenceListError"] = proto.RepeatedField( + proto.MESSAGE, + number=2, + message="ReferenceListError", + ) + + class ReferenceList(proto.Message): r"""A reference list. Reference lists are user-defined lists of values which users can @@ -382,4 +439,25 @@ class ReferenceListEntry(proto.Message): ) +class ReferenceListError(proto.Message): + r"""The error generated when verifying the reference list. + + Attributes: + line_number (int): + 1-indexed line number where the error occurs. + General list errors are indexed at -1. + error_message (str): + Message explaining why the line is invalid. + """ + + line_number: int = proto.Field( + proto.INT32, + number=1, + ) + error_message: str = proto.Field( + proto.STRING, + number=2, + ) + + __all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/packages/google-cloud-chronicle/google/cloud/chronicle_v1/types/rule.py b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/types/rule.py index 6d1f5dd98553..0bce542dcd09 100644 --- a/packages/google-cloud-chronicle/google/cloud/chronicle_v1/types/rule.py +++ b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/types/rule.py @@ -37,6 +37,8 @@ "ListRulesResponse", "UpdateRuleRequest", "DeleteRuleRequest", + "VerifyRuleTextRequest", + "VerifyRuleTextResponse", "ListRuleRevisionsRequest", "ListRuleRevisionsResponse", "CreateRetrohuntRequest", @@ -692,6 +694,55 @@ class DeleteRuleRequest(proto.Message): ) +class VerifyRuleTextRequest(proto.Message): + r"""Request message for VerifyRuleText method. + + Attributes: + instance (str): + Required. The name of the parent resource, which is the + SecOps instance associated with the request. Format: + ``projects/{project}/locations/{location}/instances/{instance}`` + rule_text (str): + Required. The rule text to verify as a UTF-8 + string. + """ + + instance: str = proto.Field( + proto.STRING, + number=1, + ) + rule_text: str = proto.Field( + proto.STRING, + number=2, + ) + + +class VerifyRuleTextResponse(proto.Message): + r"""Response message for VerifyRuleText method. + + Attributes: + success (bool): + Whether or not the rule text was successfully + verified. + compilation_diagnostics (MutableSequence[google.cloud.chronicle_v1.types.CompilationDiagnostic]): + A list of a rule's corresponding compilation + diagnostic messages such as compilation errors + and compilation warnings. + """ + + success: bool = proto.Field( + proto.BOOL, + number=1, + ) + compilation_diagnostics: MutableSequence["CompilationDiagnostic"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=3, + message="CompilationDiagnostic", + ) + ) + + class ListRuleRevisionsRequest(proto.Message): r"""Request message for ListRuleRevisions method. diff --git a/packages/google-cloud-chronicle/google/cloud/chronicle_v1/types/rule_execution_error.py b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/types/rule_execution_error.py new file mode 100644 index 000000000000..c78531a8848e --- /dev/null +++ b/packages/google-cloud-chronicle/google/cloud/chronicle_v1/types/rule_execution_error.py @@ -0,0 +1,192 @@ +# -*- coding: utf-8 -*- +# Copyright 2026 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 google.rpc.status_pb2 as status_pb2 # type: ignore +import google.type.interval_pb2 as interval_pb2 # type: ignore +import proto # type: ignore + +__protobuf__ = proto.module( + package="google.cloud.chronicle.v1", + manifest={ + "ListRuleExecutionErrorsRequest", + "ListRuleExecutionErrorsResponse", + "RuleExecutionError", + }, +) + + +class ListRuleExecutionErrorsRequest(proto.Message): + r"""Request message for ListRuleExecutionErrors. + + Attributes: + parent (str): + Required. The instance to list rule execution + errors from. Format: + + projects/{project}/locations/{location}/instances/{instance} + page_size (int): + The maximum number of rule execution errors + to return. The service may return fewer than + this value. If unspecified, at most 1000 rule + execution errors will be returned. The maximum + value is 10000; values above 10000 will be + coerced to 10000. + page_token (str): + A page token, received from a previous + ``ListRuleExecutionErrors`` call. Provide this to retrieve + the subsequent page. + + When paginating, all other parameters provided to + ``ListRuleExecutionErrors`` must match the call that + provided the page token. + filter (str): + A filter that can be used to retrieve specific rule + execution errors. Only the following filters are allowed: + + :: + + rule = "{Rule.name}" + curated_rule = "{CuratedRule.name}" + + The value for rule or curated_rule must be a valid rule + resource name or a valid curated rule resource name + specified in quotes. + + For 'rule', an optional 'revision_id' can be specified which + can be used to fetch errors for a given revision of the + rule. A '-' is also allowed to fetch errors across all + revisions of the rule. If unspecified, only errors + corresponding to the most recent revision of the rule will + be returned. So these variations are all allowed: + + :: + + rule = "{Rule.name}" + rule = "{Rule.name}@{Rule.revision_id}" + rule = "{Rule.name}@-" + + Revision IDs are not supported for curated rules. + """ + + 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, + ) + + +class ListRuleExecutionErrorsResponse(proto.Message): + r"""Response message for ListRuleExecutionErrors. + + Attributes: + rule_execution_errors (MutableSequence[google.cloud.chronicle_v1.types.RuleExecutionError]): + List of rule execution errors. + next_page_token (str): + A token, which can be sent as ``page_token`` to retrieve the + next page. If this field is omitted, there are no subsequent + pages. + """ + + @property + def raw_page(self): + return self + + rule_execution_errors: MutableSequence["RuleExecutionError"] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="RuleExecutionError", + ) + next_page_token: str = proto.Field( + proto.STRING, + number=2, + ) + + +class RuleExecutionError(proto.Message): + r"""The RuleExecutionError resource represents an error generated + from running/deploying a rule. + + 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: + rule (str): + Output only. The resource name of the rule + that generated the rule execution error. + + This field is a member of `oneof`_ ``source``. + curated_rule (str): + Output only. The resource name of the curated + rule that generated the rule execution error. + + This field is a member of `oneof`_ ``source``. + name (str): + Output only. The resource name of the rule execution error. + Format: + projects/{project}/locations/{location}/instances/{instance}/ruleExecutionErrors/{rule_execution_error} + error (google.rpc.status_pb2.Status): + Output only. The error status corresponding + with the rule execution error. + time_range (google.type.interval_pb2.Interval): + Output only. The event time range that the + rule execution error corresponds with. + """ + + rule: str = proto.Field( + proto.STRING, + number=4, + oneof="source", + ) + curated_rule: str = proto.Field( + proto.STRING, + number=5, + oneof="source", + ) + name: str = proto.Field( + proto.STRING, + number=1, + ) + error: status_pb2.Status = proto.Field( + proto.MESSAGE, + number=2, + message=status_pb2.Status, + ) + time_range: interval_pb2.Interval = proto.Field( + proto.MESSAGE, + number=3, + message=interval_pb2.Interval, + ) + + +__all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/packages/google-cloud-chronicle/samples/generated_samples/chronicle_v1_generated_reference_list_service_verify_reference_list_async.py b/packages/google-cloud-chronicle/samples/generated_samples/chronicle_v1_generated_reference_list_service_verify_reference_list_async.py new file mode 100644 index 000000000000..48577e71ce55 --- /dev/null +++ b/packages/google-cloud-chronicle/samples/generated_samples/chronicle_v1_generated_reference_list_service_verify_reference_list_async.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +# Copyright 2026 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 VerifyReferenceList +# 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-chronicle + + +# [START chronicle_v1_generated_ReferenceListService_VerifyReferenceList_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 chronicle_v1 + + +async def sample_verify_reference_list(): + # Create a client + client = chronicle_v1.ReferenceListServiceAsyncClient() + + # Initialize request argument(s) + entries = chronicle_v1.ReferenceListEntry() + entries.value = "value_value" + + request = chronicle_v1.VerifyReferenceListRequest( + instance="instance_value", + syntax_type="REFERENCE_LIST_SYNTAX_TYPE_CIDR", + entries=entries, + ) + + # Make the request + response = await client.verify_reference_list(request=request) + + # Handle the response + print(response) + + +# [END chronicle_v1_generated_ReferenceListService_VerifyReferenceList_async] diff --git a/packages/google-cloud-chronicle/samples/generated_samples/chronicle_v1_generated_reference_list_service_verify_reference_list_sync.py b/packages/google-cloud-chronicle/samples/generated_samples/chronicle_v1_generated_reference_list_service_verify_reference_list_sync.py new file mode 100644 index 000000000000..10bd54548a91 --- /dev/null +++ b/packages/google-cloud-chronicle/samples/generated_samples/chronicle_v1_generated_reference_list_service_verify_reference_list_sync.py @@ -0,0 +1,58 @@ +# -*- coding: utf-8 -*- +# Copyright 2026 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 VerifyReferenceList +# 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-chronicle + + +# [START chronicle_v1_generated_ReferenceListService_VerifyReferenceList_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 chronicle_v1 + + +def sample_verify_reference_list(): + # Create a client + client = chronicle_v1.ReferenceListServiceClient() + + # Initialize request argument(s) + entries = chronicle_v1.ReferenceListEntry() + entries.value = "value_value" + + request = chronicle_v1.VerifyReferenceListRequest( + instance="instance_value", + syntax_type="REFERENCE_LIST_SYNTAX_TYPE_CIDR", + entries=entries, + ) + + # Make the request + response = client.verify_reference_list(request=request) + + # Handle the response + print(response) + + +# [END chronicle_v1_generated_ReferenceListService_VerifyReferenceList_sync] diff --git a/packages/google-cloud-chronicle/samples/generated_samples/chronicle_v1_generated_rule_execution_error_service_list_rule_execution_errors_async.py b/packages/google-cloud-chronicle/samples/generated_samples/chronicle_v1_generated_rule_execution_error_service_list_rule_execution_errors_async.py new file mode 100644 index 000000000000..e06033573918 --- /dev/null +++ b/packages/google-cloud-chronicle/samples/generated_samples/chronicle_v1_generated_rule_execution_error_service_list_rule_execution_errors_async.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- +# Copyright 2026 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 ListRuleExecutionErrors +# 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-chronicle + + +# [START chronicle_v1_generated_RuleExecutionErrorService_ListRuleExecutionErrors_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 chronicle_v1 + + +async def sample_list_rule_execution_errors(): + # Create a client + client = chronicle_v1.RuleExecutionErrorServiceAsyncClient() + + # Initialize request argument(s) + request = chronicle_v1.ListRuleExecutionErrorsRequest( + parent="parent_value", + ) + + # Make the request + page_result = client.list_rule_execution_errors(request=request) + + # Handle the response + async for response in page_result: + print(response) + + +# [END chronicle_v1_generated_RuleExecutionErrorService_ListRuleExecutionErrors_async] diff --git a/packages/google-cloud-chronicle/samples/generated_samples/chronicle_v1_generated_rule_execution_error_service_list_rule_execution_errors_sync.py b/packages/google-cloud-chronicle/samples/generated_samples/chronicle_v1_generated_rule_execution_error_service_list_rule_execution_errors_sync.py new file mode 100644 index 000000000000..825134d19481 --- /dev/null +++ b/packages/google-cloud-chronicle/samples/generated_samples/chronicle_v1_generated_rule_execution_error_service_list_rule_execution_errors_sync.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- +# Copyright 2026 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 ListRuleExecutionErrors +# 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-chronicle + + +# [START chronicle_v1_generated_RuleExecutionErrorService_ListRuleExecutionErrors_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 chronicle_v1 + + +def sample_list_rule_execution_errors(): + # Create a client + client = chronicle_v1.RuleExecutionErrorServiceClient() + + # Initialize request argument(s) + request = chronicle_v1.ListRuleExecutionErrorsRequest( + parent="parent_value", + ) + + # Make the request + page_result = client.list_rule_execution_errors(request=request) + + # Handle the response + for response in page_result: + print(response) + + +# [END chronicle_v1_generated_RuleExecutionErrorService_ListRuleExecutionErrors_sync] diff --git a/packages/google-cloud-chronicle/samples/generated_samples/chronicle_v1_generated_rule_service_verify_rule_text_async.py b/packages/google-cloud-chronicle/samples/generated_samples/chronicle_v1_generated_rule_service_verify_rule_text_async.py new file mode 100644 index 000000000000..99d57fac4045 --- /dev/null +++ b/packages/google-cloud-chronicle/samples/generated_samples/chronicle_v1_generated_rule_service_verify_rule_text_async.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- +# Copyright 2026 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 VerifyRuleText +# 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-chronicle + + +# [START chronicle_v1_generated_RuleService_VerifyRuleText_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 chronicle_v1 + + +async def sample_verify_rule_text(): + # Create a client + client = chronicle_v1.RuleServiceAsyncClient() + + # Initialize request argument(s) + request = chronicle_v1.VerifyRuleTextRequest( + instance="instance_value", + rule_text="rule_text_value", + ) + + # Make the request + response = await client.verify_rule_text(request=request) + + # Handle the response + print(response) + + +# [END chronicle_v1_generated_RuleService_VerifyRuleText_async] diff --git a/packages/google-cloud-chronicle/samples/generated_samples/chronicle_v1_generated_rule_service_verify_rule_text_sync.py b/packages/google-cloud-chronicle/samples/generated_samples/chronicle_v1_generated_rule_service_verify_rule_text_sync.py new file mode 100644 index 000000000000..d862d419908e --- /dev/null +++ b/packages/google-cloud-chronicle/samples/generated_samples/chronicle_v1_generated_rule_service_verify_rule_text_sync.py @@ -0,0 +1,54 @@ +# -*- coding: utf-8 -*- +# Copyright 2026 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 VerifyRuleText +# 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-chronicle + + +# [START chronicle_v1_generated_RuleService_VerifyRuleText_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 chronicle_v1 + + +def sample_verify_rule_text(): + # Create a client + client = chronicle_v1.RuleServiceClient() + + # Initialize request argument(s) + request = chronicle_v1.VerifyRuleTextRequest( + instance="instance_value", + rule_text="rule_text_value", + ) + + # Make the request + response = client.verify_rule_text(request=request) + + # Handle the response + print(response) + + +# [END chronicle_v1_generated_RuleService_VerifyRuleText_sync] diff --git a/packages/google-cloud-chronicle/samples/generated_samples/snippet_metadata_google.cloud.chronicle.v1.json b/packages/google-cloud-chronicle/samples/generated_samples/snippet_metadata_google.cloud.chronicle.v1.json index 7ff526195bf3..4b1a6b17c619 100644 --- a/packages/google-cloud-chronicle/samples/generated_samples/snippet_metadata_google.cloud.chronicle.v1.json +++ b/packages/google-cloud-chronicle/samples/generated_samples/snippet_metadata_google.cloud.chronicle.v1.json @@ -9440,6 +9440,320 @@ ], "title": "chronicle_v1_generated_reference_list_service_update_reference_list_sync.py" }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.chronicle_v1.ReferenceListServiceAsyncClient", + "shortName": "ReferenceListServiceAsyncClient" + }, + "fullName": "google.cloud.chronicle_v1.ReferenceListServiceAsyncClient.verify_reference_list", + "method": { + "fullName": "google.cloud.chronicle.v1.ReferenceListService.VerifyReferenceList", + "service": { + "fullName": "google.cloud.chronicle.v1.ReferenceListService", + "shortName": "ReferenceListService" + }, + "shortName": "VerifyReferenceList" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.chronicle_v1.types.VerifyReferenceListRequest" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, Union[str, bytes]]]" + } + ], + "resultType": "google.cloud.chronicle_v1.types.VerifyReferenceListResponse", + "shortName": "verify_reference_list" + }, + "description": "Sample for VerifyReferenceList", + "file": "chronicle_v1_generated_reference_list_service_verify_reference_list_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "chronicle_v1_generated_ReferenceListService_VerifyReferenceList_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": "chronicle_v1_generated_reference_list_service_verify_reference_list_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.chronicle_v1.ReferenceListServiceClient", + "shortName": "ReferenceListServiceClient" + }, + "fullName": "google.cloud.chronicle_v1.ReferenceListServiceClient.verify_reference_list", + "method": { + "fullName": "google.cloud.chronicle.v1.ReferenceListService.VerifyReferenceList", + "service": { + "fullName": "google.cloud.chronicle.v1.ReferenceListService", + "shortName": "ReferenceListService" + }, + "shortName": "VerifyReferenceList" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.chronicle_v1.types.VerifyReferenceListRequest" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, Union[str, bytes]]]" + } + ], + "resultType": "google.cloud.chronicle_v1.types.VerifyReferenceListResponse", + "shortName": "verify_reference_list" + }, + "description": "Sample for VerifyReferenceList", + "file": "chronicle_v1_generated_reference_list_service_verify_reference_list_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "chronicle_v1_generated_ReferenceListService_VerifyReferenceList_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": "chronicle_v1_generated_reference_list_service_verify_reference_list_sync.py" + }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.chronicle_v1.RuleExecutionErrorServiceAsyncClient", + "shortName": "RuleExecutionErrorServiceAsyncClient" + }, + "fullName": "google.cloud.chronicle_v1.RuleExecutionErrorServiceAsyncClient.list_rule_execution_errors", + "method": { + "fullName": "google.cloud.chronicle.v1.RuleExecutionErrorService.ListRuleExecutionErrors", + "service": { + "fullName": "google.cloud.chronicle.v1.RuleExecutionErrorService", + "shortName": "RuleExecutionErrorService" + }, + "shortName": "ListRuleExecutionErrors" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.chronicle_v1.types.ListRuleExecutionErrorsRequest" + }, + { + "name": "parent", + "type": "str" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, Union[str, bytes]]]" + } + ], + "resultType": "google.cloud.chronicle_v1.services.rule_execution_error_service.pagers.ListRuleExecutionErrorsAsyncPager", + "shortName": "list_rule_execution_errors" + }, + "description": "Sample for ListRuleExecutionErrors", + "file": "chronicle_v1_generated_rule_execution_error_service_list_rule_execution_errors_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "chronicle_v1_generated_RuleExecutionErrorService_ListRuleExecutionErrors_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": "chronicle_v1_generated_rule_execution_error_service_list_rule_execution_errors_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.chronicle_v1.RuleExecutionErrorServiceClient", + "shortName": "RuleExecutionErrorServiceClient" + }, + "fullName": "google.cloud.chronicle_v1.RuleExecutionErrorServiceClient.list_rule_execution_errors", + "method": { + "fullName": "google.cloud.chronicle.v1.RuleExecutionErrorService.ListRuleExecutionErrors", + "service": { + "fullName": "google.cloud.chronicle.v1.RuleExecutionErrorService", + "shortName": "RuleExecutionErrorService" + }, + "shortName": "ListRuleExecutionErrors" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.chronicle_v1.types.ListRuleExecutionErrorsRequest" + }, + { + "name": "parent", + "type": "str" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, Union[str, bytes]]]" + } + ], + "resultType": "google.cloud.chronicle_v1.services.rule_execution_error_service.pagers.ListRuleExecutionErrorsPager", + "shortName": "list_rule_execution_errors" + }, + "description": "Sample for ListRuleExecutionErrors", + "file": "chronicle_v1_generated_rule_execution_error_service_list_rule_execution_errors_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "chronicle_v1_generated_RuleExecutionErrorService_ListRuleExecutionErrors_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": "chronicle_v1_generated_rule_execution_error_service_list_rule_execution_errors_sync.py" + }, { "canonical": true, "clientMethod": { @@ -11397,6 +11711,175 @@ } ], "title": "chronicle_v1_generated_rule_service_update_rule_sync.py" + }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.chronicle_v1.RuleServiceAsyncClient", + "shortName": "RuleServiceAsyncClient" + }, + "fullName": "google.cloud.chronicle_v1.RuleServiceAsyncClient.verify_rule_text", + "method": { + "fullName": "google.cloud.chronicle.v1.RuleService.VerifyRuleText", + "service": { + "fullName": "google.cloud.chronicle.v1.RuleService", + "shortName": "RuleService" + }, + "shortName": "VerifyRuleText" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.chronicle_v1.types.VerifyRuleTextRequest" + }, + { + "name": "instance", + "type": "str" + }, + { + "name": "rule_text", + "type": "str" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, Union[str, bytes]]]" + } + ], + "resultType": "google.cloud.chronicle_v1.types.VerifyRuleTextResponse", + "shortName": "verify_rule_text" + }, + "description": "Sample for VerifyRuleText", + "file": "chronicle_v1_generated_rule_service_verify_rule_text_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "chronicle_v1_generated_RuleService_VerifyRuleText_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": "chronicle_v1_generated_rule_service_verify_rule_text_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.chronicle_v1.RuleServiceClient", + "shortName": "RuleServiceClient" + }, + "fullName": "google.cloud.chronicle_v1.RuleServiceClient.verify_rule_text", + "method": { + "fullName": "google.cloud.chronicle.v1.RuleService.VerifyRuleText", + "service": { + "fullName": "google.cloud.chronicle.v1.RuleService", + "shortName": "RuleService" + }, + "shortName": "VerifyRuleText" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.chronicle_v1.types.VerifyRuleTextRequest" + }, + { + "name": "instance", + "type": "str" + }, + { + "name": "rule_text", + "type": "str" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, Union[str, bytes]]]" + } + ], + "resultType": "google.cloud.chronicle_v1.types.VerifyRuleTextResponse", + "shortName": "verify_rule_text" + }, + "description": "Sample for VerifyRuleText", + "file": "chronicle_v1_generated_rule_service_verify_rule_text_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "chronicle_v1_generated_RuleService_VerifyRuleText_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": "chronicle_v1_generated_rule_service_verify_rule_text_sync.py" } ] } diff --git a/packages/google-cloud-chronicle/tests/unit/gapic/chronicle_v1/test_reference_list_service.py b/packages/google-cloud-chronicle/tests/unit/gapic/chronicle_v1/test_reference_list_service.py index ab8bd59e5917..e81b69811745 100644 --- a/packages/google-cloud-chronicle/tests/unit/gapic/chronicle_v1/test_reference_list_service.py +++ b/packages/google-cloud-chronicle/tests/unit/gapic/chronicle_v1/test_reference_list_service.py @@ -1376,7 +1376,11 @@ def test_reference_list_service_client_create_channel_credentials_file( credentials=file_creds, credentials_file=None, quota_project_id=None, - default_scopes=("https://www.googleapis.com/auth/cloud-platform",), + default_scopes=( + "https://www.googleapis.com/auth/chronicle", + "https://www.googleapis.com/auth/chronicle.readonly", + "https://www.googleapis.com/auth/cloud-platform", + ), scopes=None, default_host="chronicle.googleapis.com", ssl_credentials=None, @@ -3069,6 +3073,265 @@ async def test_update_reference_list_flattened_error_async(): ) +@pytest.mark.parametrize( + "request_type", + [ + reference_list.VerifyReferenceListRequest(), + {}, + ], +) +def test_verify_reference_list(request_type, transport: str = "grpc"): + client = ReferenceListServiceClient( + 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.verify_reference_list), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = reference_list.VerifyReferenceListResponse( + success=True, + ) + response = client.verify_reference_list(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = reference_list.VerifyReferenceListRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, reference_list.VerifyReferenceListResponse) + assert response.success is True + + +def test_verify_reference_list_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 = ReferenceListServiceClient( + 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 = reference_list.VerifyReferenceListRequest( + instance="instance_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.verify_reference_list), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.verify_reference_list(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + request_msg = reference_list.VerifyReferenceListRequest( + instance="instance_value", + ) + assert args[0] == request_msg + + +def test_verify_reference_list_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = ReferenceListServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.verify_reference_list + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.verify_reference_list] = ( + mock_rpc + ) + request = {} + client.verify_reference_list(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.verify_reference_list(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_verify_reference_list_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = ReferenceListServiceAsyncClient( + credentials=async_anonymous_credentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.verify_reference_list + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.AsyncMock() + mock_rpc.return_value = mock.Mock() + client._client._transport._wrapped_methods[ + client._client._transport.verify_reference_list + ] = mock_rpc + + request = {} + await client.verify_reference_list(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + await client.verify_reference_list(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +@pytest.mark.parametrize( + "request_type", + [ + reference_list.VerifyReferenceListRequest(), + {}, + ], +) +async def test_verify_reference_list_async( + request_type, transport: str = "grpc_asyncio" +): + client = ReferenceListServiceAsyncClient( + credentials=async_anonymous_credentials(), + 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.verify_reference_list), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + reference_list.VerifyReferenceListResponse( + success=True, + ) + ) + response = await client.verify_reference_list(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = reference_list.VerifyReferenceListRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, reference_list.VerifyReferenceListResponse) + assert response.success is True + + +def test_verify_reference_list_field_headers(): + client = ReferenceListServiceClient( + 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 = reference_list.VerifyReferenceListRequest() + + request.instance = "instance_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.verify_reference_list), "__call__" + ) as call: + call.return_value = reference_list.VerifyReferenceListResponse() + client.verify_reference_list(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", + "instance=instance_value", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_verify_reference_list_field_headers_async(): + client = ReferenceListServiceAsyncClient( + credentials=async_anonymous_credentials(), + ) + + # 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 = reference_list.VerifyReferenceListRequest() + + request.instance = "instance_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.verify_reference_list), "__call__" + ) as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + reference_list.VerifyReferenceListResponse() + ) + await client.verify_reference_list(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", + "instance=instance_value", + ) in kw["metadata"] + + def test_get_reference_list_rest_use_cached_wrapped_rpc(): # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, # instead of constructing them on each call @@ -3922,42 +4185,177 @@ def test_update_reference_list_rest_flattened_error(transport: str = "rest"): ) -def test_credentials_transport_error(): - # It is an error to provide credentials and a transport instance. - transport = transports.ReferenceListServiceGrpcTransport( - credentials=ga_credentials.AnonymousCredentials(), - ) - with pytest.raises(ValueError): +def test_verify_reference_list_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: client = ReferenceListServiceClient( credentials=ga_credentials.AnonymousCredentials(), - transport=transport, + transport="rest", ) - # It is an error to provide a credentials file and a transport instance. - transport = transports.ReferenceListServiceGrpcTransport( - credentials=ga_credentials.AnonymousCredentials(), - ) - with pytest.raises(ValueError): - client = ReferenceListServiceClient( - client_options={"credentials_file": "credentials.json"}, - transport=transport, + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.verify_reference_list + in client._transport._wrapped_methods ) - # It is an error to provide an api_key and a transport instance. - transport = transports.ReferenceListServiceGrpcTransport( - credentials=ga_credentials.AnonymousCredentials(), - ) - options = client_options.ClientOptions() - options.api_key = "api_key" - with pytest.raises(ValueError): - client = ReferenceListServiceClient( - client_options=options, - transport=transport, + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.verify_reference_list] = ( + mock_rpc ) - # It is an error to provide an api_key and a credential. - options = client_options.ClientOptions() - options.api_key = "api_key" + request = {} + client.verify_reference_list(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.verify_reference_list(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_verify_reference_list_rest_required_fields( + request_type=reference_list.VerifyReferenceListRequest, +): + transport_class = transports.ReferenceListServiceRestTransport + + request_init = {} + request_init["instance"] = "" + 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() + ).verify_reference_list._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + jsonified_request["instance"] = "instance_value" + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).verify_reference_list._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + assert "instance" in jsonified_request + assert jsonified_request["instance"] == "instance_value" + + client = ReferenceListServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = reference_list.VerifyReferenceListResponse() + # 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 = reference_list.VerifyReferenceListResponse.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 + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + + response = client.verify_reference_list(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert sorted(expected_params) == sorted(actual_params) + + +def test_verify_reference_list_rest_unset_required_fields(): + transport = transports.ReferenceListServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.verify_reference_list._get_unset_required_fields({}) + assert set(unset_fields) == ( + set(()) + & set( + ( + "instance", + "syntaxType", + "entries", + ) + ) + ) + + +def test_credentials_transport_error(): + # It is an error to provide credentials and a transport instance. + transport = transports.ReferenceListServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + with pytest.raises(ValueError): + client = ReferenceListServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # It is an error to provide a credentials file and a transport instance. + transport = transports.ReferenceListServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + with pytest.raises(ValueError): + client = ReferenceListServiceClient( + client_options={"credentials_file": "credentials.json"}, + transport=transport, + ) + + # It is an error to provide an api_key and a transport instance. + transport = transports.ReferenceListServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + options = client_options.ClientOptions() + options.api_key = "api_key" + with pytest.raises(ValueError): + client = ReferenceListServiceClient( + 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 = ReferenceListServiceClient( client_options=options, credentials=ga_credentials.AnonymousCredentials() @@ -4116,6 +4514,28 @@ def test_update_reference_list_empty_call_grpc(): assert args[0] == request_msg +# This test is a coverage failsafe to make sure that totally empty calls, +# i.e. request == None and no flattened fields passed, work. +def test_verify_reference_list_empty_call_grpc(): + client = ReferenceListServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Mock the actual call, and fake the request. + with mock.patch.object( + type(client.transport.verify_reference_list), "__call__" + ) as call: + call.return_value = reference_list.VerifyReferenceListResponse() + client.verify_reference_list(request=None) + + # Establish that the underlying stub method was called. + call.assert_called() + _, args, _ = call.mock_calls[0] + request_msg = reference_list.VerifyReferenceListRequest() + assert args[0] == request_msg + + def test_transport_kind_grpc_asyncio(): transport = ReferenceListServiceAsyncClient.get_transport_class("grpc_asyncio")( credentials=async_anonymous_credentials() @@ -4257,6 +4677,34 @@ async def test_update_reference_list_empty_call_grpc_asyncio(): assert args[0] == request_msg +# This test is a coverage failsafe to make sure that totally empty calls, +# i.e. request == None and no flattened fields passed, work. +@pytest.mark.asyncio +async def test_verify_reference_list_empty_call_grpc_asyncio(): + client = ReferenceListServiceAsyncClient( + credentials=async_anonymous_credentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call, and fake the request. + with mock.patch.object( + type(client.transport.verify_reference_list), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + reference_list.VerifyReferenceListResponse( + success=True, + ) + ) + await client.verify_reference_list(request=None) + + # Establish that the underlying stub method was called. + call.assert_called() + _, args, _ = call.mock_calls[0] + request_msg = reference_list.VerifyReferenceListRequest() + assert args[0] == request_msg + + def test_transport_kind_rest(): transport = ReferenceListServiceClient.get_transport_class("rest")( credentials=ga_credentials.AnonymousCredentials() @@ -5018,6 +5466,142 @@ def test_update_reference_list_rest_interceptors(null_interceptor): post_with_metadata.assert_called_once() +def test_verify_reference_list_rest_bad_request( + request_type=reference_list.VerifyReferenceListRequest, +): + client = ReferenceListServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + # send a request that will satisfy transcoding + request_init = {"instance": "projects/sample1/locations/sample2/instances/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 = mock.Mock() + json_return_value = "" + response_value.json = mock.Mock(return_value={}) + response_value.status_code = 400 + response_value.request = mock.Mock() + req.return_value = response_value + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + client.verify_reference_list(request) + + +@pytest.mark.parametrize( + "request_type", + [ + reference_list.VerifyReferenceListRequest, + dict, + ], +) +def test_verify_reference_list_rest_call_success(request_type): + client = ReferenceListServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + # send a request that will satisfy transcoding + request_init = {"instance": "projects/sample1/locations/sample2/instances/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 = reference_list.VerifyReferenceListResponse( + success=True, + ) + + # Wrap the value into a proper Response obj + response_value = mock.Mock() + response_value.status_code = 200 + + # Convert return value to protobuf type + return_value = reference_list.VerifyReferenceListResponse.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 + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + response = client.verify_reference_list(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, reference_list.VerifyReferenceListResponse) + assert response.success is True + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_verify_reference_list_rest_interceptors(null_interceptor): + transport = transports.ReferenceListServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.ReferenceListServiceRestInterceptor(), + ) + client = ReferenceListServiceClient(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.ReferenceListServiceRestInterceptor, "post_verify_reference_list" + ) as post, + mock.patch.object( + transports.ReferenceListServiceRestInterceptor, + "post_verify_reference_list_with_metadata", + ) as post_with_metadata, + mock.patch.object( + transports.ReferenceListServiceRestInterceptor, "pre_verify_reference_list" + ) as pre, + ): + pre.assert_not_called() + post.assert_not_called() + post_with_metadata.assert_not_called() + pb_message = reference_list.VerifyReferenceListRequest.pb( + reference_list.VerifyReferenceListRequest() + ) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = mock.Mock() + req.return_value.status_code = 200 + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + return_value = reference_list.VerifyReferenceListResponse.to_json( + reference_list.VerifyReferenceListResponse() + ) + req.return_value.content = return_value + + request = reference_list.VerifyReferenceListRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = reference_list.VerifyReferenceListResponse() + post_with_metadata.return_value = ( + reference_list.VerifyReferenceListResponse(), + metadata, + ) + + client.verify_reference_list( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + post_with_metadata.assert_called_once() + + def test_cancel_operation_rest_bad_request( request_type=operations_pb2.CancelOperationRequest, ): @@ -5376,6 +5960,27 @@ def test_update_reference_list_empty_call_rest(): assert args[0] == request_msg +# This test is a coverage failsafe to make sure that totally empty calls, +# i.e. request == None and no flattened fields passed, work. +def test_verify_reference_list_empty_call_rest(): + client = ReferenceListServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the actual call, and fake the request. + with mock.patch.object( + type(client.transport.verify_reference_list), "__call__" + ) as call: + client.verify_reference_list(request=None) + + # Establish that the underlying stub method was called. + call.assert_called() + _, args, _ = call.mock_calls[0] + request_msg = reference_list.VerifyReferenceListRequest() + assert args[0] == request_msg + + def test_transport_grpc_default(): # A client should use the gRPC transport by default. client = ReferenceListServiceClient( @@ -5413,6 +6018,7 @@ def test_reference_list_service_base_transport(): "list_reference_lists", "create_reference_list", "update_reference_list", + "verify_reference_list", "get_operation", "cancel_operation", "delete_operation", @@ -5453,7 +6059,11 @@ def test_reference_list_service_base_transport_with_credentials_file(): load_creds.assert_called_once_with( "credentials.json", scopes=None, - default_scopes=("https://www.googleapis.com/auth/cloud-platform",), + default_scopes=( + "https://www.googleapis.com/auth/chronicle", + "https://www.googleapis.com/auth/chronicle.readonly", + "https://www.googleapis.com/auth/cloud-platform", + ), quota_project_id="octopus", ) @@ -5479,7 +6089,11 @@ def test_reference_list_service_auth_adc(): ReferenceListServiceClient() adc.assert_called_once_with( scopes=None, - default_scopes=("https://www.googleapis.com/auth/cloud-platform",), + default_scopes=( + "https://www.googleapis.com/auth/chronicle", + "https://www.googleapis.com/auth/chronicle.readonly", + "https://www.googleapis.com/auth/cloud-platform", + ), quota_project_id=None, ) @@ -5499,7 +6113,11 @@ def test_reference_list_service_transport_auth_adc(transport_class): 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",), + default_scopes=( + "https://www.googleapis.com/auth/chronicle", + "https://www.googleapis.com/auth/chronicle.readonly", + "https://www.googleapis.com/auth/cloud-platform", + ), quota_project_id="octopus", ) @@ -5552,7 +6170,11 @@ def test_reference_list_service_transport_create_channel(transport_class, grpc_h credentials=creds, credentials_file=None, quota_project_id="octopus", - default_scopes=("https://www.googleapis.com/auth/cloud-platform",), + default_scopes=( + "https://www.googleapis.com/auth/chronicle", + "https://www.googleapis.com/auth/chronicle.readonly", + "https://www.googleapis.com/auth/cloud-platform", + ), scopes=["1", "2"], default_host="chronicle.googleapis.com", ssl_credentials=None, @@ -5696,6 +6318,9 @@ def test_reference_list_service_client_transport_session_collision(transport_nam session1 = client1.transport.update_reference_list._session session2 = client2.transport.update_reference_list._session assert session1 != session2 + session1 = client1.transport.verify_reference_list._session + session2 = client2.transport.verify_reference_list._session + assert session1 != session2 def test_reference_list_service_grpc_transport_channel(): @@ -5825,11 +6450,37 @@ def test_reference_list_service_transport_channel_mtls_with_adc(transport_class) assert transport.grpc_channel == mock_grpc_channel -def test_reference_list_path(): +def test_instance_path(): project = "squid" location = "clam" instance = "whelk" - reference_list = "octopus" + expected = "projects/{project}/locations/{location}/instances/{instance}".format( + project=project, + location=location, + instance=instance, + ) + actual = ReferenceListServiceClient.instance_path(project, location, instance) + assert expected == actual + + +def test_parse_instance_path(): + expected = { + "project": "octopus", + "location": "oyster", + "instance": "nudibranch", + } + path = ReferenceListServiceClient.instance_path(**expected) + + # Check that the path construction is reversible. + actual = ReferenceListServiceClient.parse_instance_path(path) + assert expected == actual + + +def test_reference_list_path(): + project = "cuttlefish" + location = "mussel" + instance = "winkle" + reference_list = "nautilus" expected = "projects/{project}/locations/{location}/instances/{instance}/referenceLists/{reference_list}".format( project=project, location=location, @@ -5844,10 +6495,10 @@ def test_reference_list_path(): def test_parse_reference_list_path(): expected = { - "project": "oyster", - "location": "nudibranch", - "instance": "cuttlefish", - "reference_list": "mussel", + "project": "scallop", + "location": "abalone", + "instance": "squid", + "reference_list": "clam", } path = ReferenceListServiceClient.reference_list_path(**expected) @@ -5857,7 +6508,7 @@ def test_parse_reference_list_path(): def test_common_billing_account_path(): - billing_account = "winkle" + billing_account = "whelk" expected = "billingAccounts/{billing_account}".format( billing_account=billing_account, ) @@ -5867,7 +6518,7 @@ def test_common_billing_account_path(): def test_parse_common_billing_account_path(): expected = { - "billing_account": "nautilus", + "billing_account": "octopus", } path = ReferenceListServiceClient.common_billing_account_path(**expected) @@ -5877,7 +6528,7 @@ def test_parse_common_billing_account_path(): def test_common_folder_path(): - folder = "scallop" + folder = "oyster" expected = "folders/{folder}".format( folder=folder, ) @@ -5887,7 +6538,7 @@ def test_common_folder_path(): def test_parse_common_folder_path(): expected = { - "folder": "abalone", + "folder": "nudibranch", } path = ReferenceListServiceClient.common_folder_path(**expected) @@ -5897,7 +6548,7 @@ def test_parse_common_folder_path(): def test_common_organization_path(): - organization = "squid" + organization = "cuttlefish" expected = "organizations/{organization}".format( organization=organization, ) @@ -5907,7 +6558,7 @@ def test_common_organization_path(): def test_parse_common_organization_path(): expected = { - "organization": "clam", + "organization": "mussel", } path = ReferenceListServiceClient.common_organization_path(**expected) @@ -5917,7 +6568,7 @@ def test_parse_common_organization_path(): def test_common_project_path(): - project = "whelk" + project = "winkle" expected = "projects/{project}".format( project=project, ) @@ -5927,7 +6578,7 @@ def test_common_project_path(): def test_parse_common_project_path(): expected = { - "project": "octopus", + "project": "nautilus", } path = ReferenceListServiceClient.common_project_path(**expected) @@ -5937,8 +6588,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, @@ -5949,8 +6600,8 @@ def test_common_location_path(): def test_parse_common_location_path(): expected = { - "project": "cuttlefish", - "location": "mussel", + "project": "squid", + "location": "clam", } path = ReferenceListServiceClient.common_location_path(**expected) diff --git a/packages/google-cloud-chronicle/tests/unit/gapic/chronicle_v1/test_rule_execution_error_service.py b/packages/google-cloud-chronicle/tests/unit/gapic/chronicle_v1/test_rule_execution_error_service.py new file mode 100644 index 000000000000..f1027b35867d --- /dev/null +++ b/packages/google-cloud-chronicle/tests/unit/gapic/chronicle_v1/test_rule_execution_error_service.py @@ -0,0 +1,4317 @@ +# -*- coding: utf-8 -*- +# Copyright 2026 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 asyncio +import json +import math +import os +from collections.abc import AsyncIterable, Iterable, Mapping, Sequence +from unittest import mock +from unittest.mock import AsyncMock + +import grpc +import pytest +from google.api_core import api_core_version +from google.protobuf import json_format +from grpc.experimental import aio +from proto.marshal.rules import wrappers +from proto.marshal.rules.dates import DurationRule, TimestampRule +from requests import PreparedRequest, Request, Response +from requests.sessions import Session + +try: + from google.auth.aio import credentials as ga_credentials_async + + HAS_GOOGLE_AUTH_AIO = True +except ImportError: # pragma: NO COVER + HAS_GOOGLE_AUTH_AIO = False + +import google.auth +from google.api_core import ( + client_options, + gapic_v1, + grpc_helpers, + grpc_helpers_async, + path_template, +) +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 +from google.auth.exceptions import MutualTLSChannelError +from google.longrunning import operations_pb2 # type: ignore +from google.oauth2 import service_account + +from google.cloud.chronicle_v1.services.rule_execution_error_service import ( + RuleExecutionErrorServiceAsyncClient, + RuleExecutionErrorServiceClient, + pagers, + transports, +) +from google.cloud.chronicle_v1.types import rule_execution_error + +CRED_INFO_JSON = { + "credential_source": "/path/to/file", + "credential_type": "service account credentials", + "principal": "service-account@example.com", +} +CRED_INFO_STRING = json.dumps(CRED_INFO_JSON) + + +async def mock_async_gen(data, chunk_size=1): + for i in range(0, len(data)): # pragma: NO COVER + chunk = data[i : i + chunk_size] + yield chunk.encode("utf-8") + + +def client_cert_source_callback(): + return b"cert bytes", b"key bytes" + + +# TODO: use async auth anon credentials by default once the minimum version of google-auth is upgraded. +# See related issue: https://github.com/googleapis/gapic-generator-python/issues/2107. +def async_anonymous_credentials(): + if HAS_GOOGLE_AUTH_AIO: + return ga_credentials_async.AnonymousCredentials() + return ga_credentials.AnonymousCredentials() + + +# 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 + ) + + +@pytest.fixture(autouse=True) +def set_event_loop(): + try: + asyncio.get_running_loop() + yield + except RuntimeError: + loop = asyncio.new_event_loop() + asyncio.set_event_loop(loop) + try: + yield + finally: + loop.close() + asyncio.set_event_loop(None) + + +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" + custom_endpoint = ".custom" + + assert RuleExecutionErrorServiceClient._get_default_mtls_endpoint(None) is None + assert ( + RuleExecutionErrorServiceClient._get_default_mtls_endpoint(api_endpoint) + == api_mtls_endpoint + ) + assert ( + RuleExecutionErrorServiceClient._get_default_mtls_endpoint(api_mtls_endpoint) + == api_mtls_endpoint + ) + assert ( + RuleExecutionErrorServiceClient._get_default_mtls_endpoint(sandbox_endpoint) + == sandbox_mtls_endpoint + ) + assert ( + RuleExecutionErrorServiceClient._get_default_mtls_endpoint( + sandbox_mtls_endpoint + ) + == sandbox_mtls_endpoint + ) + assert ( + RuleExecutionErrorServiceClient._get_default_mtls_endpoint(non_googleapi) + == non_googleapi + ) + assert ( + RuleExecutionErrorServiceClient._get_default_mtls_endpoint(custom_endpoint) + == custom_endpoint + ) + + +def test__read_environment_variables(): + assert RuleExecutionErrorServiceClient._read_environment_variables() == ( + False, + "auto", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "true"}): + assert RuleExecutionErrorServiceClient._read_environment_variables() == ( + True, + "auto", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "false"}): + assert RuleExecutionErrorServiceClient._read_environment_variables() == ( + False, + "auto", + None, + ) + + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"} + ): + if not hasattr(google.auth.transport.mtls, "should_use_client_cert"): + with pytest.raises(ValueError) as excinfo: + RuleExecutionErrorServiceClient._read_environment_variables() + assert ( + str(excinfo.value) + == "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be either `true` or `false`" + ) + else: + assert RuleExecutionErrorServiceClient._read_environment_variables() == ( + False, + "auto", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "never"}): + assert RuleExecutionErrorServiceClient._read_environment_variables() == ( + False, + "never", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "always"}): + assert RuleExecutionErrorServiceClient._read_environment_variables() == ( + False, + "always", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "auto"}): + assert RuleExecutionErrorServiceClient._read_environment_variables() == ( + False, + "auto", + None, + ) + + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "Unsupported"}): + with pytest.raises(MutualTLSChannelError) as excinfo: + RuleExecutionErrorServiceClient._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 RuleExecutionErrorServiceClient._read_environment_variables() == ( + False, + "auto", + "foo.com", + ) + + +def test_use_client_cert_effective(): + # Test case 1: Test when `should_use_client_cert` returns True. + # We mock the `should_use_client_cert` function to simulate a scenario where + # the google-auth library supports automatic mTLS and determines that a + # client certificate should be used. + if hasattr(google.auth.transport.mtls, "should_use_client_cert"): + with mock.patch( + "google.auth.transport.mtls.should_use_client_cert", return_value=True + ): + assert RuleExecutionErrorServiceClient._use_client_cert_effective() is True + + # Test case 2: Test when `should_use_client_cert` returns False. + # We mock the `should_use_client_cert` function to simulate a scenario where + # the google-auth library supports automatic mTLS and determines that a + # client certificate should NOT be used. + if hasattr(google.auth.transport.mtls, "should_use_client_cert"): + with mock.patch( + "google.auth.transport.mtls.should_use_client_cert", return_value=False + ): + assert RuleExecutionErrorServiceClient._use_client_cert_effective() is False + + # Test case 3: Test when `should_use_client_cert` is unavailable and the + # `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to "true". + if not hasattr(google.auth.transport.mtls, "should_use_client_cert"): + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "true"}): + assert RuleExecutionErrorServiceClient._use_client_cert_effective() is True + + # Test case 4: Test when `should_use_client_cert` is unavailable and the + # `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to "false". + if not hasattr(google.auth.transport.mtls, "should_use_client_cert"): + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "false"} + ): + assert RuleExecutionErrorServiceClient._use_client_cert_effective() is False + + # Test case 5: Test when `should_use_client_cert` is unavailable and the + # `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to "True". + if not hasattr(google.auth.transport.mtls, "should_use_client_cert"): + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "True"}): + assert RuleExecutionErrorServiceClient._use_client_cert_effective() is True + + # Test case 6: Test when `should_use_client_cert` is unavailable and the + # `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to "False". + if not hasattr(google.auth.transport.mtls, "should_use_client_cert"): + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "False"} + ): + assert RuleExecutionErrorServiceClient._use_client_cert_effective() is False + + # Test case 7: Test when `should_use_client_cert` is unavailable and the + # `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to "TRUE". + if not hasattr(google.auth.transport.mtls, "should_use_client_cert"): + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "TRUE"}): + assert RuleExecutionErrorServiceClient._use_client_cert_effective() is True + + # Test case 8: Test when `should_use_client_cert` is unavailable and the + # `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to "FALSE". + if not hasattr(google.auth.transport.mtls, "should_use_client_cert"): + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "FALSE"} + ): + assert RuleExecutionErrorServiceClient._use_client_cert_effective() is False + + # Test case 9: Test when `should_use_client_cert` is unavailable and the + # `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is not set. + # In this case, the method should return False, which is the default value. + if not hasattr(google.auth.transport.mtls, "should_use_client_cert"): + with mock.patch.dict(os.environ, clear=True): + assert RuleExecutionErrorServiceClient._use_client_cert_effective() is False + + # Test case 10: Test when `should_use_client_cert` is unavailable and the + # `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to an invalid value. + # The method should raise a ValueError as the environment variable must be either + # "true" or "false". + if not hasattr(google.auth.transport.mtls, "should_use_client_cert"): + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "unsupported"} + ): + with pytest.raises(ValueError): + RuleExecutionErrorServiceClient._use_client_cert_effective() + + # Test case 11: Test when `should_use_client_cert` is available and the + # `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is set to an invalid value. + # The method should return False as the environment variable is set to an invalid value. + if hasattr(google.auth.transport.mtls, "should_use_client_cert"): + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "unsupported"} + ): + assert RuleExecutionErrorServiceClient._use_client_cert_effective() is False + + # Test case 12: Test when `should_use_client_cert` is available and the + # `GOOGLE_API_USE_CLIENT_CERTIFICATE` environment variable is unset. Also, + # the GOOGLE_API_CONFIG environment variable is unset. + if hasattr(google.auth.transport.mtls, "should_use_client_cert"): + with mock.patch.dict(os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": ""}): + with mock.patch.dict(os.environ, {"GOOGLE_API_CERTIFICATE_CONFIG": ""}): + assert ( + RuleExecutionErrorServiceClient._use_client_cert_effective() + is False + ) + + +def test__get_client_cert_source(): + mock_provided_cert_source = mock.Mock() + mock_default_cert_source = mock.Mock() + + assert RuleExecutionErrorServiceClient._get_client_cert_source(None, False) is None + assert ( + RuleExecutionErrorServiceClient._get_client_cert_source( + mock_provided_cert_source, False + ) + is None + ) + assert ( + RuleExecutionErrorServiceClient._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 ( + RuleExecutionErrorServiceClient._get_client_cert_source(None, True) + is mock_default_cert_source + ) + assert ( + RuleExecutionErrorServiceClient._get_client_cert_source( + mock_provided_cert_source, "true" + ) + is mock_provided_cert_source + ) + + +@mock.patch.object( + RuleExecutionErrorServiceClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(RuleExecutionErrorServiceClient), +) +@mock.patch.object( + RuleExecutionErrorServiceAsyncClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(RuleExecutionErrorServiceAsyncClient), +) +def test__get_api_endpoint(): + api_override = "foo.com" + mock_client_cert_source = mock.Mock() + default_universe = RuleExecutionErrorServiceClient._DEFAULT_UNIVERSE + default_endpoint = ( + RuleExecutionErrorServiceClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=default_universe + ) + ) + mock_universe = "bar.com" + mock_endpoint = RuleExecutionErrorServiceClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=mock_universe + ) + + assert ( + RuleExecutionErrorServiceClient._get_api_endpoint( + api_override, mock_client_cert_source, default_universe, "always" + ) + == api_override + ) + assert ( + RuleExecutionErrorServiceClient._get_api_endpoint( + None, mock_client_cert_source, default_universe, "auto" + ) + == RuleExecutionErrorServiceClient.DEFAULT_MTLS_ENDPOINT + ) + assert ( + RuleExecutionErrorServiceClient._get_api_endpoint( + None, None, default_universe, "auto" + ) + == default_endpoint + ) + assert ( + RuleExecutionErrorServiceClient._get_api_endpoint( + None, None, default_universe, "always" + ) + == RuleExecutionErrorServiceClient.DEFAULT_MTLS_ENDPOINT + ) + assert ( + RuleExecutionErrorServiceClient._get_api_endpoint( + None, mock_client_cert_source, default_universe, "always" + ) + == RuleExecutionErrorServiceClient.DEFAULT_MTLS_ENDPOINT + ) + assert ( + RuleExecutionErrorServiceClient._get_api_endpoint( + None, None, mock_universe, "never" + ) + == mock_endpoint + ) + assert ( + RuleExecutionErrorServiceClient._get_api_endpoint( + None, None, default_universe, "never" + ) + == default_endpoint + ) + + with pytest.raises(MutualTLSChannelError) as excinfo: + RuleExecutionErrorServiceClient._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 ( + RuleExecutionErrorServiceClient._get_universe_domain( + client_universe_domain, universe_domain_env + ) + == client_universe_domain + ) + assert ( + RuleExecutionErrorServiceClient._get_universe_domain(None, universe_domain_env) + == universe_domain_env + ) + assert ( + RuleExecutionErrorServiceClient._get_universe_domain(None, None) + == RuleExecutionErrorServiceClient._DEFAULT_UNIVERSE + ) + + with pytest.raises(ValueError) as excinfo: + RuleExecutionErrorServiceClient._get_universe_domain("", None) + assert str(excinfo.value) == "Universe Domain cannot be an empty string." + + +@pytest.mark.parametrize( + "error_code,cred_info_json,show_cred_info", + [ + (401, CRED_INFO_JSON, True), + (403, CRED_INFO_JSON, True), + (404, CRED_INFO_JSON, True), + (500, CRED_INFO_JSON, False), + (401, None, False), + (403, None, False), + (404, None, False), + (500, None, False), + ], +) +def test__add_cred_info_for_auth_errors(error_code, cred_info_json, show_cred_info): + cred = mock.Mock(["get_cred_info"]) + cred.get_cred_info = mock.Mock(return_value=cred_info_json) + client = RuleExecutionErrorServiceClient(credentials=cred) + client._transport._credentials = cred + + error = core_exceptions.GoogleAPICallError("message", details=["foo"]) + error.code = error_code + + client._add_cred_info_for_auth_errors(error) + if show_cred_info: + assert error.details == ["foo", CRED_INFO_STRING] + else: + assert error.details == ["foo"] + + +@pytest.mark.parametrize("error_code", [401, 403, 404, 500]) +def test__add_cred_info_for_auth_errors_no_get_cred_info(error_code): + cred = mock.Mock([]) + assert not hasattr(cred, "get_cred_info") + client = RuleExecutionErrorServiceClient(credentials=cred) + client._transport._credentials = cred + + error = core_exceptions.GoogleAPICallError("message", details=[]) + error.code = error_code + + client._add_cred_info_for_auth_errors(error) + assert error.details == [] + + +@pytest.mark.parametrize( + "client_class,transport_name", + [ + (RuleExecutionErrorServiceClient, "grpc"), + (RuleExecutionErrorServiceAsyncClient, "grpc_asyncio"), + (RuleExecutionErrorServiceClient, "rest"), + ], +) +def test_rule_execution_error_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 == ( + "chronicle.googleapis.com:443" + if transport_name in ["grpc", "grpc_asyncio"] + else "https://chronicle.googleapis.com" + ) + + +@pytest.mark.parametrize( + "transport_class,transport_name", + [ + (transports.RuleExecutionErrorServiceGrpcTransport, "grpc"), + (transports.RuleExecutionErrorServiceGrpcAsyncIOTransport, "grpc_asyncio"), + (transports.RuleExecutionErrorServiceRestTransport, "rest"), + ], +) +def test_rule_execution_error_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", + [ + (RuleExecutionErrorServiceClient, "grpc"), + (RuleExecutionErrorServiceAsyncClient, "grpc_asyncio"), + (RuleExecutionErrorServiceClient, "rest"), + ], +) +def test_rule_execution_error_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 == ( + "chronicle.googleapis.com:443" + if transport_name in ["grpc", "grpc_asyncio"] + else "https://chronicle.googleapis.com" + ) + + +def test_rule_execution_error_service_client_get_transport_class(): + transport = RuleExecutionErrorServiceClient.get_transport_class() + available_transports = [ + transports.RuleExecutionErrorServiceGrpcTransport, + transports.RuleExecutionErrorServiceRestTransport, + ] + assert transport in available_transports + + transport = RuleExecutionErrorServiceClient.get_transport_class("grpc") + assert transport == transports.RuleExecutionErrorServiceGrpcTransport + + +@pytest.mark.parametrize( + "client_class,transport_class,transport_name", + [ + ( + RuleExecutionErrorServiceClient, + transports.RuleExecutionErrorServiceGrpcTransport, + "grpc", + ), + ( + RuleExecutionErrorServiceAsyncClient, + transports.RuleExecutionErrorServiceGrpcAsyncIOTransport, + "grpc_asyncio", + ), + ( + RuleExecutionErrorServiceClient, + transports.RuleExecutionErrorServiceRestTransport, + "rest", + ), + ], +) +@mock.patch.object( + RuleExecutionErrorServiceClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(RuleExecutionErrorServiceClient), +) +@mock.patch.object( + RuleExecutionErrorServiceAsyncClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(RuleExecutionErrorServiceAsyncClient), +) +def test_rule_execution_error_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( + RuleExecutionErrorServiceClient, "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( + RuleExecutionErrorServiceClient, "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 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", + [ + ( + RuleExecutionErrorServiceClient, + transports.RuleExecutionErrorServiceGrpcTransport, + "grpc", + "true", + ), + ( + RuleExecutionErrorServiceAsyncClient, + transports.RuleExecutionErrorServiceGrpcAsyncIOTransport, + "grpc_asyncio", + "true", + ), + ( + RuleExecutionErrorServiceClient, + transports.RuleExecutionErrorServiceGrpcTransport, + "grpc", + "false", + ), + ( + RuleExecutionErrorServiceAsyncClient, + transports.RuleExecutionErrorServiceGrpcAsyncIOTransport, + "grpc_asyncio", + "false", + ), + ( + RuleExecutionErrorServiceClient, + transports.RuleExecutionErrorServiceRestTransport, + "rest", + "true", + ), + ( + RuleExecutionErrorServiceClient, + transports.RuleExecutionErrorServiceRestTransport, + "rest", + "false", + ), + ], +) +@mock.patch.object( + RuleExecutionErrorServiceClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(RuleExecutionErrorServiceClient), +) +@mock.patch.object( + RuleExecutionErrorServiceAsyncClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(RuleExecutionErrorServiceAsyncClient), +) +@mock.patch.dict(os.environ, {"GOOGLE_API_USE_MTLS_ENDPOINT": "auto"}) +def test_rule_execution_error_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", + [RuleExecutionErrorServiceClient, RuleExecutionErrorServiceAsyncClient], +) +@mock.patch.object( + RuleExecutionErrorServiceClient, + "DEFAULT_ENDPOINT", + modify_default_endpoint(RuleExecutionErrorServiceClient), +) +@mock.patch.object( + RuleExecutionErrorServiceAsyncClient, + "DEFAULT_ENDPOINT", + modify_default_endpoint(RuleExecutionErrorServiceAsyncClient), +) +def test_rule_execution_error_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_CLIENT_CERTIFICATE is "Unsupported". + with mock.patch.dict( + os.environ, {"GOOGLE_API_USE_CLIENT_CERTIFICATE": "Unsupported"} + ): + if hasattr(google.auth.transport.mtls, "should_use_client_cert"): + 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 cases for mTLS enablement when GOOGLE_API_USE_CLIENT_CERTIFICATE is unset. + test_cases = [ + ( + # With workloads present in config, mTLS is enabled. + { + "version": 1, + "cert_configs": { + "workload": { + "cert_path": "path/to/cert/file", + "key_path": "path/to/key/file", + } + }, + }, + mock_client_cert_source, + ), + ( + # With workloads not present in config, mTLS is disabled. + { + "version": 1, + "cert_configs": {}, + }, + None, + ), + ] + if hasattr(google.auth.transport.mtls, "should_use_client_cert"): + for config_data, expected_cert_source in test_cases: + env = os.environ.copy() + env.pop("GOOGLE_API_USE_CLIENT_CERTIFICATE", None) + with mock.patch.dict(os.environ, env, clear=True): + config_filename = "mock_certificate_config.json" + config_file_content = json.dumps(config_data) + m = mock.mock_open(read_data=config_file_content) + with mock.patch("builtins.open", m): + with mock.patch.dict( + os.environ, {"GOOGLE_API_CERTIFICATE_CONFIG": config_filename} + ): + 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 expected_cert_source + + # Test cases for mTLS enablement when GOOGLE_API_USE_CLIENT_CERTIFICATE is unset(empty). + test_cases = [ + ( + # With workloads present in config, mTLS is enabled. + { + "version": 1, + "cert_configs": { + "workload": { + "cert_path": "path/to/cert/file", + "key_path": "path/to/key/file", + } + }, + }, + mock_client_cert_source, + ), + ( + # With workloads not present in config, mTLS is disabled. + { + "version": 1, + "cert_configs": {}, + }, + None, + ), + ] + if hasattr(google.auth.transport.mtls, "should_use_client_cert"): + for config_data, expected_cert_source in test_cases: + env = os.environ.copy() + env.pop("GOOGLE_API_USE_CLIENT_CERTIFICATE", "") + with mock.patch.dict(os.environ, env, clear=True): + config_filename = "mock_certificate_config.json" + config_file_content = json.dumps(config_data) + m = mock.mock_open(read_data=config_file_content) + with mock.patch("builtins.open", m): + with mock.patch.dict( + os.environ, {"GOOGLE_API_CERTIFICATE_CONFIG": config_filename} + ): + 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 expected_cert_source + + # 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`" + ) + + +@pytest.mark.parametrize( + "client_class", + [RuleExecutionErrorServiceClient, RuleExecutionErrorServiceAsyncClient], +) +@mock.patch.object( + RuleExecutionErrorServiceClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(RuleExecutionErrorServiceClient), +) +@mock.patch.object( + RuleExecutionErrorServiceAsyncClient, + "_DEFAULT_ENDPOINT_TEMPLATE", + modify_default_endpoint_template(RuleExecutionErrorServiceAsyncClient), +) +def test_rule_execution_error_service_client_client_api_endpoint(client_class): + mock_client_cert_source = client_cert_source_callback + api_override = "foo.com" + default_universe = RuleExecutionErrorServiceClient._DEFAULT_UNIVERSE + default_endpoint = ( + RuleExecutionErrorServiceClient._DEFAULT_ENDPOINT_TEMPLATE.format( + UNIVERSE_DOMAIN=default_universe + ) + ) + mock_universe = "bar.com" + mock_endpoint = RuleExecutionErrorServiceClient._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", + [ + ( + RuleExecutionErrorServiceClient, + transports.RuleExecutionErrorServiceGrpcTransport, + "grpc", + ), + ( + RuleExecutionErrorServiceAsyncClient, + transports.RuleExecutionErrorServiceGrpcAsyncIOTransport, + "grpc_asyncio", + ), + ( + RuleExecutionErrorServiceClient, + transports.RuleExecutionErrorServiceRestTransport, + "rest", + ), + ], +) +def test_rule_execution_error_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", + [ + ( + RuleExecutionErrorServiceClient, + transports.RuleExecutionErrorServiceGrpcTransport, + "grpc", + grpc_helpers, + ), + ( + RuleExecutionErrorServiceAsyncClient, + transports.RuleExecutionErrorServiceGrpcAsyncIOTransport, + "grpc_asyncio", + grpc_helpers_async, + ), + ( + RuleExecutionErrorServiceClient, + transports.RuleExecutionErrorServiceRestTransport, + "rest", + None, + ), + ], +) +def test_rule_execution_error_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_rule_execution_error_service_client_client_options_from_dict(): + with mock.patch( + "google.cloud.chronicle_v1.services.rule_execution_error_service.transports.RuleExecutionErrorServiceGrpcTransport.__init__" + ) as grpc_transport: + grpc_transport.return_value = None + client = RuleExecutionErrorServiceClient( + 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", + [ + ( + RuleExecutionErrorServiceClient, + transports.RuleExecutionErrorServiceGrpcTransport, + "grpc", + grpc_helpers, + ), + ( + RuleExecutionErrorServiceAsyncClient, + transports.RuleExecutionErrorServiceGrpcAsyncIOTransport, + "grpc_asyncio", + grpc_helpers_async, + ), + ], +) +def test_rule_execution_error_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( + "chronicle.googleapis.com:443", + credentials=file_creds, + credentials_file=None, + quota_project_id=None, + default_scopes=( + "https://www.googleapis.com/auth/chronicle", + "https://www.googleapis.com/auth/chronicle.readonly", + "https://www.googleapis.com/auth/cloud-platform", + ), + scopes=None, + default_host="chronicle.googleapis.com", + ssl_credentials=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + +@pytest.mark.parametrize( + "request_type", + [ + rule_execution_error.ListRuleExecutionErrorsRequest(), + {}, + ], +) +def test_list_rule_execution_errors(request_type, transport: str = "grpc"): + client = RuleExecutionErrorServiceClient( + 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_rule_execution_errors), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = rule_execution_error.ListRuleExecutionErrorsResponse( + next_page_token="next_page_token_value", + ) + response = client.list_rule_execution_errors(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = rule_execution_error.ListRuleExecutionErrorsRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, pagers.ListRuleExecutionErrorsPager) + assert response.next_page_token == "next_page_token_value" + + +def test_list_rule_execution_errors_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 = RuleExecutionErrorServiceClient( + 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 = rule_execution_error.ListRuleExecutionErrorsRequest( + parent="parent_value", + page_token="page_token_value", + filter="filter_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_rule_execution_errors), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.list_rule_execution_errors(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + request_msg = rule_execution_error.ListRuleExecutionErrorsRequest( + parent="parent_value", + page_token="page_token_value", + filter="filter_value", + ) + assert args[0] == request_msg + + +def test_list_rule_execution_errors_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = RuleExecutionErrorServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.list_rule_execution_errors + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.list_rule_execution_errors + ] = mock_rpc + request = {} + client.list_rule_execution_errors(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.list_rule_execution_errors(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_list_rule_execution_errors_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = RuleExecutionErrorServiceAsyncClient( + credentials=async_anonymous_credentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.list_rule_execution_errors + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.AsyncMock() + mock_rpc.return_value = mock.Mock() + client._client._transport._wrapped_methods[ + client._client._transport.list_rule_execution_errors + ] = mock_rpc + + request = {} + await client.list_rule_execution_errors(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + await client.list_rule_execution_errors(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +@pytest.mark.parametrize( + "request_type", + [ + rule_execution_error.ListRuleExecutionErrorsRequest(), + {}, + ], +) +async def test_list_rule_execution_errors_async( + request_type, transport: str = "grpc_asyncio" +): + client = RuleExecutionErrorServiceAsyncClient( + credentials=async_anonymous_credentials(), + 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_rule_execution_errors), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + rule_execution_error.ListRuleExecutionErrorsResponse( + next_page_token="next_page_token_value", + ) + ) + response = await client.list_rule_execution_errors(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = rule_execution_error.ListRuleExecutionErrorsRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, pagers.ListRuleExecutionErrorsAsyncPager) + assert response.next_page_token == "next_page_token_value" + + +def test_list_rule_execution_errors_field_headers(): + client = RuleExecutionErrorServiceClient( + 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 = rule_execution_error.ListRuleExecutionErrorsRequest() + + request.parent = "parent_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_rule_execution_errors), "__call__" + ) as call: + call.return_value = rule_execution_error.ListRuleExecutionErrorsResponse() + client.list_rule_execution_errors(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_rule_execution_errors_field_headers_async(): + client = RuleExecutionErrorServiceAsyncClient( + credentials=async_anonymous_credentials(), + ) + + # 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 = rule_execution_error.ListRuleExecutionErrorsRequest() + + request.parent = "parent_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_rule_execution_errors), "__call__" + ) as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + rule_execution_error.ListRuleExecutionErrorsResponse() + ) + await client.list_rule_execution_errors(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_rule_execution_errors_flattened(): + client = RuleExecutionErrorServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_rule_execution_errors), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = rule_execution_error.ListRuleExecutionErrorsResponse() + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.list_rule_execution_errors( + 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_rule_execution_errors_flattened_error(): + client = RuleExecutionErrorServiceClient( + 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_rule_execution_errors( + rule_execution_error.ListRuleExecutionErrorsRequest(), + parent="parent_value", + ) + + +@pytest.mark.asyncio +async def test_list_rule_execution_errors_flattened_async(): + client = RuleExecutionErrorServiceAsyncClient( + credentials=async_anonymous_credentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_rule_execution_errors), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = rule_execution_error.ListRuleExecutionErrorsResponse() + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + rule_execution_error.ListRuleExecutionErrorsResponse() + ) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.list_rule_execution_errors( + 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_rule_execution_errors_flattened_error_async(): + client = RuleExecutionErrorServiceAsyncClient( + credentials=async_anonymous_credentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + await client.list_rule_execution_errors( + rule_execution_error.ListRuleExecutionErrorsRequest(), + parent="parent_value", + ) + + +def test_list_rule_execution_errors_pager(transport_name: str = "grpc"): + client = RuleExecutionErrorServiceClient( + 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_rule_execution_errors), "__call__" + ) as call: + # Set the response to a series of pages. + call.side_effect = ( + rule_execution_error.ListRuleExecutionErrorsResponse( + rule_execution_errors=[ + rule_execution_error.RuleExecutionError(), + rule_execution_error.RuleExecutionError(), + rule_execution_error.RuleExecutionError(), + ], + next_page_token="abc", + ), + rule_execution_error.ListRuleExecutionErrorsResponse( + rule_execution_errors=[], + next_page_token="def", + ), + rule_execution_error.ListRuleExecutionErrorsResponse( + rule_execution_errors=[ + rule_execution_error.RuleExecutionError(), + ], + next_page_token="ghi", + ), + rule_execution_error.ListRuleExecutionErrorsResponse( + rule_execution_errors=[ + rule_execution_error.RuleExecutionError(), + rule_execution_error.RuleExecutionError(), + ], + ), + RuntimeError, + ) + + expected_metadata = () + retry = retries.Retry() + timeout = 5 + expected_metadata = tuple(expected_metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("parent", ""),)), + ) + pager = client.list_rule_execution_errors( + request={}, retry=retry, timeout=timeout + ) + + assert pager._metadata == expected_metadata + assert pager._retry == retry + assert pager._timeout == timeout + + results = list(pager) + assert len(results) == 6 + assert all( + isinstance(i, rule_execution_error.RuleExecutionError) for i in results + ) + + +def test_list_rule_execution_errors_pages(transport_name: str = "grpc"): + client = RuleExecutionErrorServiceClient( + 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_rule_execution_errors), "__call__" + ) as call: + # Set the response to a series of pages. + call.side_effect = ( + rule_execution_error.ListRuleExecutionErrorsResponse( + rule_execution_errors=[ + rule_execution_error.RuleExecutionError(), + rule_execution_error.RuleExecutionError(), + rule_execution_error.RuleExecutionError(), + ], + next_page_token="abc", + ), + rule_execution_error.ListRuleExecutionErrorsResponse( + rule_execution_errors=[], + next_page_token="def", + ), + rule_execution_error.ListRuleExecutionErrorsResponse( + rule_execution_errors=[ + rule_execution_error.RuleExecutionError(), + ], + next_page_token="ghi", + ), + rule_execution_error.ListRuleExecutionErrorsResponse( + rule_execution_errors=[ + rule_execution_error.RuleExecutionError(), + rule_execution_error.RuleExecutionError(), + ], + ), + RuntimeError, + ) + pages = list(client.list_rule_execution_errors(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_rule_execution_errors_async_pager(): + client = RuleExecutionErrorServiceAsyncClient( + credentials=async_anonymous_credentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_rule_execution_errors), + "__call__", + new_callable=mock.AsyncMock, + ) as call: + # Set the response to a series of pages. + call.side_effect = ( + rule_execution_error.ListRuleExecutionErrorsResponse( + rule_execution_errors=[ + rule_execution_error.RuleExecutionError(), + rule_execution_error.RuleExecutionError(), + rule_execution_error.RuleExecutionError(), + ], + next_page_token="abc", + ), + rule_execution_error.ListRuleExecutionErrorsResponse( + rule_execution_errors=[], + next_page_token="def", + ), + rule_execution_error.ListRuleExecutionErrorsResponse( + rule_execution_errors=[ + rule_execution_error.RuleExecutionError(), + ], + next_page_token="ghi", + ), + rule_execution_error.ListRuleExecutionErrorsResponse( + rule_execution_errors=[ + rule_execution_error.RuleExecutionError(), + rule_execution_error.RuleExecutionError(), + ], + ), + RuntimeError, + ) + async_pager = await client.list_rule_execution_errors( + 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, rule_execution_error.RuleExecutionError) for i in responses + ) + + +@pytest.mark.asyncio +async def test_list_rule_execution_errors_async_pages(): + client = RuleExecutionErrorServiceAsyncClient( + credentials=async_anonymous_credentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.list_rule_execution_errors), + "__call__", + new_callable=mock.AsyncMock, + ) as call: + # Set the response to a series of pages. + call.side_effect = ( + rule_execution_error.ListRuleExecutionErrorsResponse( + rule_execution_errors=[ + rule_execution_error.RuleExecutionError(), + rule_execution_error.RuleExecutionError(), + rule_execution_error.RuleExecutionError(), + ], + next_page_token="abc", + ), + rule_execution_error.ListRuleExecutionErrorsResponse( + rule_execution_errors=[], + next_page_token="def", + ), + rule_execution_error.ListRuleExecutionErrorsResponse( + rule_execution_errors=[ + rule_execution_error.RuleExecutionError(), + ], + next_page_token="ghi", + ), + rule_execution_error.ListRuleExecutionErrorsResponse( + rule_execution_errors=[ + rule_execution_error.RuleExecutionError(), + rule_execution_error.RuleExecutionError(), + ], + ), + RuntimeError, + ) + pages = [] + async for page_ in (await client.list_rule_execution_errors(request={})).pages: + pages.append(page_) + for page_, token in zip(pages, ["abc", "def", "ghi", ""]): + assert page_.raw_page.next_page_token == token + + +def test_list_rule_execution_errors_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = RuleExecutionErrorServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.list_rule_execution_errors + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.list_rule_execution_errors + ] = mock_rpc + + request = {} + client.list_rule_execution_errors(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.list_rule_execution_errors(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_list_rule_execution_errors_rest_required_fields( + request_type=rule_execution_error.ListRuleExecutionErrorsRequest, +): + transport_class = transports.RuleExecutionErrorServiceRestTransport + + 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_rule_execution_errors._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_rule_execution_errors._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 "parent" in jsonified_request + assert jsonified_request["parent"] == "parent_value" + + client = RuleExecutionErrorServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type(**request_init) + + # Designate an appropriate value for the returned response. + return_value = rule_execution_error.ListRuleExecutionErrorsResponse() + # 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 = rule_execution_error.ListRuleExecutionErrorsResponse.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 + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + + response = client.list_rule_execution_errors(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert sorted(expected_params) == sorted(actual_params) + + +def test_list_rule_execution_errors_rest_unset_required_fields(): + transport = transports.RuleExecutionErrorServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.list_rule_execution_errors._get_unset_required_fields({}) + assert set(unset_fields) == ( + set( + ( + "filter", + "pageSize", + "pageToken", + ) + ) + & set(("parent",)) + ) + + +def test_list_rule_execution_errors_rest_flattened(): + client = RuleExecutionErrorServiceClient( + 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 = rule_execution_error.ListRuleExecutionErrorsResponse() + + # get arguments that satisfy an http rule for this method + sample_request = { + "parent": "projects/sample1/locations/sample2/instances/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 = rule_execution_error.ListRuleExecutionErrorsResponse.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 + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + + client.list_rule_execution_errors(**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/{parent=projects/*/locations/*/instances/*}/ruleExecutionErrors" + % client.transport._host, + args[1], + ) + + +def test_list_rule_execution_errors_rest_flattened_error(transport: str = "rest"): + client = RuleExecutionErrorServiceClient( + 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_rule_execution_errors( + rule_execution_error.ListRuleExecutionErrorsRequest(), + parent="parent_value", + ) + + +def test_list_rule_execution_errors_rest_pager(transport: str = "rest"): + client = RuleExecutionErrorServiceClient( + 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 = ( + rule_execution_error.ListRuleExecutionErrorsResponse( + rule_execution_errors=[ + rule_execution_error.RuleExecutionError(), + rule_execution_error.RuleExecutionError(), + rule_execution_error.RuleExecutionError(), + ], + next_page_token="abc", + ), + rule_execution_error.ListRuleExecutionErrorsResponse( + rule_execution_errors=[], + next_page_token="def", + ), + rule_execution_error.ListRuleExecutionErrorsResponse( + rule_execution_errors=[ + rule_execution_error.RuleExecutionError(), + ], + next_page_token="ghi", + ), + rule_execution_error.ListRuleExecutionErrorsResponse( + rule_execution_errors=[ + rule_execution_error.RuleExecutionError(), + rule_execution_error.RuleExecutionError(), + ], + ), + ) + # Two responses for two calls + response = response + response + + # Wrap the values into proper Response objs + response = tuple( + rule_execution_error.ListRuleExecutionErrorsResponse.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/instances/sample3" + } + + pager = client.list_rule_execution_errors(request=sample_request) + + results = list(pager) + assert len(results) == 6 + assert all( + isinstance(i, rule_execution_error.RuleExecutionError) for i in results + ) + + pages = list(client.list_rule_execution_errors(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. + transport = transports.RuleExecutionErrorServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + with pytest.raises(ValueError): + client = RuleExecutionErrorServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport=transport, + ) + + # It is an error to provide a credentials file and a transport instance. + transport = transports.RuleExecutionErrorServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + with pytest.raises(ValueError): + client = RuleExecutionErrorServiceClient( + client_options={"credentials_file": "credentials.json"}, + transport=transport, + ) + + # It is an error to provide an api_key and a transport instance. + transport = transports.RuleExecutionErrorServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + options = client_options.ClientOptions() + options.api_key = "api_key" + with pytest.raises(ValueError): + client = RuleExecutionErrorServiceClient( + 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 = RuleExecutionErrorServiceClient( + client_options=options, credentials=ga_credentials.AnonymousCredentials() + ) + + # It is an error to provide scopes and a transport instance. + transport = transports.RuleExecutionErrorServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + with pytest.raises(ValueError): + client = RuleExecutionErrorServiceClient( + client_options={"scopes": ["1", "2"]}, + transport=transport, + ) + + +def test_transport_instance(): + # A client may be instantiated with a custom transport instance. + transport = transports.RuleExecutionErrorServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + client = RuleExecutionErrorServiceClient(transport=transport) + assert client.transport is transport + + +def test_transport_get_channel(): + # A client may be instantiated with a custom transport instance. + transport = transports.RuleExecutionErrorServiceGrpcTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + channel = transport.grpc_channel + assert channel + + transport = transports.RuleExecutionErrorServiceGrpcAsyncIOTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + channel = transport.grpc_channel + assert channel + + +@pytest.mark.parametrize( + "transport_class", + [ + transports.RuleExecutionErrorServiceGrpcTransport, + transports.RuleExecutionErrorServiceGrpcAsyncIOTransport, + transports.RuleExecutionErrorServiceRestTransport, + ], +) +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() + + +def test_transport_kind_grpc(): + transport = RuleExecutionErrorServiceClient.get_transport_class("grpc")( + credentials=ga_credentials.AnonymousCredentials() + ) + assert transport.kind == "grpc" + + +def test_initialize_client_w_grpc(): + client = RuleExecutionErrorServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="grpc" + ) + assert client is not None + + +# This test is a coverage failsafe to make sure that totally empty calls, +# i.e. request == None and no flattened fields passed, work. +def test_list_rule_execution_errors_empty_call_grpc(): + client = RuleExecutionErrorServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Mock the actual call, and fake the request. + with mock.patch.object( + type(client.transport.list_rule_execution_errors), "__call__" + ) as call: + call.return_value = rule_execution_error.ListRuleExecutionErrorsResponse() + client.list_rule_execution_errors(request=None) + + # Establish that the underlying stub method was called. + call.assert_called() + _, args, _ = call.mock_calls[0] + request_msg = rule_execution_error.ListRuleExecutionErrorsRequest() + assert args[0] == request_msg + + +def test_transport_kind_grpc_asyncio(): + transport = RuleExecutionErrorServiceAsyncClient.get_transport_class( + "grpc_asyncio" + )(credentials=async_anonymous_credentials()) + assert transport.kind == "grpc_asyncio" + + +def test_initialize_client_w_grpc_asyncio(): + client = RuleExecutionErrorServiceAsyncClient( + credentials=async_anonymous_credentials(), transport="grpc_asyncio" + ) + assert client is not None + + +# This test is a coverage failsafe to make sure that totally empty calls, +# i.e. request == None and no flattened fields passed, work. +@pytest.mark.asyncio +async def test_list_rule_execution_errors_empty_call_grpc_asyncio(): + client = RuleExecutionErrorServiceAsyncClient( + credentials=async_anonymous_credentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call, and fake the request. + with mock.patch.object( + type(client.transport.list_rule_execution_errors), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + rule_execution_error.ListRuleExecutionErrorsResponse( + next_page_token="next_page_token_value", + ) + ) + await client.list_rule_execution_errors(request=None) + + # Establish that the underlying stub method was called. + call.assert_called() + _, args, _ = call.mock_calls[0] + request_msg = rule_execution_error.ListRuleExecutionErrorsRequest() + assert args[0] == request_msg + + +def test_transport_kind_rest(): + transport = RuleExecutionErrorServiceClient.get_transport_class("rest")( + credentials=ga_credentials.AnonymousCredentials() + ) + assert transport.kind == "rest" + + +def test_list_rule_execution_errors_rest_bad_request( + request_type=rule_execution_error.ListRuleExecutionErrorsRequest, +): + client = RuleExecutionErrorServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + # send a request that will satisfy transcoding + request_init = {"parent": "projects/sample1/locations/sample2/instances/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 = mock.Mock() + json_return_value = "" + response_value.json = mock.Mock(return_value={}) + response_value.status_code = 400 + response_value.request = mock.Mock() + req.return_value = response_value + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + client.list_rule_execution_errors(request) + + +@pytest.mark.parametrize( + "request_type", + [ + rule_execution_error.ListRuleExecutionErrorsRequest, + dict, + ], +) +def test_list_rule_execution_errors_rest_call_success(request_type): + client = RuleExecutionErrorServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + # send a request that will satisfy transcoding + request_init = {"parent": "projects/sample1/locations/sample2/instances/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 = rule_execution_error.ListRuleExecutionErrorsResponse( + next_page_token="next_page_token_value", + ) + + # Wrap the value into a proper Response obj + response_value = mock.Mock() + response_value.status_code = 200 + + # Convert return value to protobuf type + return_value = rule_execution_error.ListRuleExecutionErrorsResponse.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 + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + response = client.list_rule_execution_errors(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, pagers.ListRuleExecutionErrorsPager) + assert response.next_page_token == "next_page_token_value" + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_list_rule_execution_errors_rest_interceptors(null_interceptor): + transport = transports.RuleExecutionErrorServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.RuleExecutionErrorServiceRestInterceptor(), + ) + client = RuleExecutionErrorServiceClient(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.RuleExecutionErrorServiceRestInterceptor, + "post_list_rule_execution_errors", + ) as post, + mock.patch.object( + transports.RuleExecutionErrorServiceRestInterceptor, + "post_list_rule_execution_errors_with_metadata", + ) as post_with_metadata, + mock.patch.object( + transports.RuleExecutionErrorServiceRestInterceptor, + "pre_list_rule_execution_errors", + ) as pre, + ): + pre.assert_not_called() + post.assert_not_called() + post_with_metadata.assert_not_called() + pb_message = rule_execution_error.ListRuleExecutionErrorsRequest.pb( + rule_execution_error.ListRuleExecutionErrorsRequest() + ) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = mock.Mock() + req.return_value.status_code = 200 + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + return_value = rule_execution_error.ListRuleExecutionErrorsResponse.to_json( + rule_execution_error.ListRuleExecutionErrorsResponse() + ) + req.return_value.content = return_value + + request = rule_execution_error.ListRuleExecutionErrorsRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = rule_execution_error.ListRuleExecutionErrorsResponse() + post_with_metadata.return_value = ( + rule_execution_error.ListRuleExecutionErrorsResponse(), + metadata, + ) + + client.list_rule_execution_errors( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + post_with_metadata.assert_called_once() + + +def test_cancel_operation_rest_bad_request( + request_type=operations_pb2.CancelOperationRequest, +): + client = RuleExecutionErrorServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type() + request = json_format.ParseDict( + { + "name": "projects/sample1/locations/sample2/instances/sample3/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() + json_return_value = "" + response_value.json = mock.Mock(return_value={}) + response_value.status_code = 400 + response_value.request = Request() + req.return_value = response_value + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + client.cancel_operation(request) + + +@pytest.mark.parametrize( + "request_type", + [ + operations_pb2.CancelOperationRequest, + dict, + ], +) +def test_cancel_operation_rest(request_type): + client = RuleExecutionErrorServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + request_init = { + "name": "projects/sample1/locations/sample2/instances/sample3/operations/sample4" + } + request = request_type(**request_init) + # Mock the http request call within the method and fake a response. + with mock.patch.object(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 = mock.Mock() + response_value.status_code = 200 + json_return_value = "{}" + response_value.content = json_return_value.encode("UTF-8") + + req.return_value = response_value + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + + response = client.cancel_operation(request) + + # Establish that the response is the type that we expect. + assert response is None + + +def test_delete_operation_rest_bad_request( + request_type=operations_pb2.DeleteOperationRequest, +): + client = RuleExecutionErrorServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type() + request = json_format.ParseDict( + { + "name": "projects/sample1/locations/sample2/instances/sample3/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() + json_return_value = "" + response_value.json = mock.Mock(return_value={}) + response_value.status_code = 400 + response_value.request = Request() + req.return_value = response_value + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + client.delete_operation(request) + + +@pytest.mark.parametrize( + "request_type", + [ + operations_pb2.DeleteOperationRequest, + dict, + ], +) +def test_delete_operation_rest(request_type): + client = RuleExecutionErrorServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + request_init = { + "name": "projects/sample1/locations/sample2/instances/sample3/operations/sample4" + } + request = request_type(**request_init) + # Mock the http request call within the method and fake a response. + with mock.patch.object(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 = mock.Mock() + response_value.status_code = 200 + json_return_value = "{}" + response_value.content = json_return_value.encode("UTF-8") + + req.return_value = response_value + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + + response = client.delete_operation(request) + + # Establish that the response is the type that we expect. + assert response is None + + +def test_get_operation_rest_bad_request( + request_type=operations_pb2.GetOperationRequest, +): + client = RuleExecutionErrorServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type() + request = json_format.ParseDict( + { + "name": "projects/sample1/locations/sample2/instances/sample3/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() + json_return_value = "" + response_value.json = mock.Mock(return_value={}) + response_value.status_code = 400 + response_value.request = Request() + req.return_value = response_value + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + client.get_operation(request) + + +@pytest.mark.parametrize( + "request_type", + [ + operations_pb2.GetOperationRequest, + dict, + ], +) +def test_get_operation_rest(request_type): + client = RuleExecutionErrorServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + request_init = { + "name": "projects/sample1/locations/sample2/instances/sample3/operations/sample4" + } + request = request_type(**request_init) + # Mock the http request call within the method and fake a response. + with mock.patch.object(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 = mock.Mock() + 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 + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + + 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( + request_type=operations_pb2.ListOperationsRequest, +): + client = RuleExecutionErrorServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + request = request_type() + request = json_format.ParseDict( + {"name": "projects/sample1/locations/sample2/instances/sample3"}, request + ) + + # Mock the http request call within the method and fake a BadRequest error. + with ( + mock.patch.object(Session, "request") as req, + pytest.raises(core_exceptions.BadRequest), + ): + # Wrap the value into a proper Response obj + response_value = Response() + json_return_value = "" + response_value.json = mock.Mock(return_value={}) + response_value.status_code = 400 + response_value.request = Request() + req.return_value = response_value + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + client.list_operations(request) + + +@pytest.mark.parametrize( + "request_type", + [ + operations_pb2.ListOperationsRequest, + dict, + ], +) +def test_list_operations_rest(request_type): + client = RuleExecutionErrorServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + request_init = {"name": "projects/sample1/locations/sample2/instances/sample3"} + request = request_type(**request_init) + # Mock the http request call within the method and fake a response. + with mock.patch.object(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 = mock.Mock() + 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 + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + + response = client.list_operations(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, operations_pb2.ListOperationsResponse) + + +def test_initialize_client_w_rest(): + client = RuleExecutionErrorServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + assert client is not None + + +# This test is a coverage failsafe to make sure that totally empty calls, +# i.e. request == None and no flattened fields passed, work. +def test_list_rule_execution_errors_empty_call_rest(): + client = RuleExecutionErrorServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the actual call, and fake the request. + with mock.patch.object( + type(client.transport.list_rule_execution_errors), "__call__" + ) as call: + client.list_rule_execution_errors(request=None) + + # Establish that the underlying stub method was called. + call.assert_called() + _, args, _ = call.mock_calls[0] + request_msg = rule_execution_error.ListRuleExecutionErrorsRequest() + assert args[0] == request_msg + + +def test_transport_grpc_default(): + # A client should use the gRPC transport by default. + client = RuleExecutionErrorServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + assert isinstance( + client.transport, + transports.RuleExecutionErrorServiceGrpcTransport, + ) + + +def test_rule_execution_error_service_base_transport_error(): + # Passing both a credentials object and credentials_file should raise an error + with pytest.raises(core_exceptions.DuplicateCredentialArgs): + transport = transports.RuleExecutionErrorServiceTransport( + credentials=ga_credentials.AnonymousCredentials(), + credentials_file="credentials.json", + ) + + +def test_rule_execution_error_service_base_transport(): + # Instantiate the base transport. + with mock.patch( + "google.cloud.chronicle_v1.services.rule_execution_error_service.transports.RuleExecutionErrorServiceTransport.__init__" + ) as Transport: + Transport.return_value = None + transport = transports.RuleExecutionErrorServiceTransport( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Every method on the transport should just blindly + # raise NotImplementedError. + methods = ( + "list_rule_execution_errors", + "get_operation", + "cancel_operation", + "delete_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_rule_execution_error_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.chronicle_v1.services.rule_execution_error_service.transports.RuleExecutionErrorServiceTransport._prep_wrapped_messages" + ) as Transport, + ): + Transport.return_value = None + load_creds.return_value = (ga_credentials.AnonymousCredentials(), None) + transport = transports.RuleExecutionErrorServiceTransport( + 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/chronicle", + "https://www.googleapis.com/auth/chronicle.readonly", + "https://www.googleapis.com/auth/cloud-platform", + ), + quota_project_id="octopus", + ) + + +def test_rule_execution_error_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.chronicle_v1.services.rule_execution_error_service.transports.RuleExecutionErrorServiceTransport._prep_wrapped_messages" + ) as Transport, + ): + Transport.return_value = None + adc.return_value = (ga_credentials.AnonymousCredentials(), None) + transport = transports.RuleExecutionErrorServiceTransport() + adc.assert_called_once() + + +def test_rule_execution_error_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) + RuleExecutionErrorServiceClient() + adc.assert_called_once_with( + scopes=None, + default_scopes=( + "https://www.googleapis.com/auth/chronicle", + "https://www.googleapis.com/auth/chronicle.readonly", + "https://www.googleapis.com/auth/cloud-platform", + ), + quota_project_id=None, + ) + + +@pytest.mark.parametrize( + "transport_class", + [ + transports.RuleExecutionErrorServiceGrpcTransport, + transports.RuleExecutionErrorServiceGrpcAsyncIOTransport, + ], +) +def test_rule_execution_error_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/chronicle", + "https://www.googleapis.com/auth/chronicle.readonly", + "https://www.googleapis.com/auth/cloud-platform", + ), + quota_project_id="octopus", + ) + + +@pytest.mark.parametrize( + "transport_class", + [ + transports.RuleExecutionErrorServiceGrpcTransport, + transports.RuleExecutionErrorServiceGrpcAsyncIOTransport, + transports.RuleExecutionErrorServiceRestTransport, + ], +) +def test_rule_execution_error_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.RuleExecutionErrorServiceGrpcTransport, grpc_helpers), + (transports.RuleExecutionErrorServiceGrpcAsyncIOTransport, grpc_helpers_async), + ], +) +def test_rule_execution_error_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( + "chronicle.googleapis.com:443", + credentials=creds, + credentials_file=None, + quota_project_id="octopus", + default_scopes=( + "https://www.googleapis.com/auth/chronicle", + "https://www.googleapis.com/auth/chronicle.readonly", + "https://www.googleapis.com/auth/cloud-platform", + ), + scopes=["1", "2"], + default_host="chronicle.googleapis.com", + ssl_credentials=None, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + +@pytest.mark.parametrize( + "transport_class", + [ + transports.RuleExecutionErrorServiceGrpcTransport, + transports.RuleExecutionErrorServiceGrpcAsyncIOTransport, + ], +) +def test_rule_execution_error_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_rule_execution_error_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.RuleExecutionErrorServiceRestTransport( + 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_rule_execution_error_service_host_no_port(transport_name): + client = RuleExecutionErrorServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + client_options=client_options.ClientOptions( + api_endpoint="chronicle.googleapis.com" + ), + transport=transport_name, + ) + assert client.transport._host == ( + "chronicle.googleapis.com:443" + if transport_name in ["grpc", "grpc_asyncio"] + else "https://chronicle.googleapis.com" + ) + + +@pytest.mark.parametrize( + "transport_name", + [ + "grpc", + "grpc_asyncio", + "rest", + ], +) +def test_rule_execution_error_service_host_with_port(transport_name): + client = RuleExecutionErrorServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + client_options=client_options.ClientOptions( + api_endpoint="chronicle.googleapis.com:8000" + ), + transport=transport_name, + ) + assert client.transport._host == ( + "chronicle.googleapis.com:8000" + if transport_name in ["grpc", "grpc_asyncio"] + else "https://chronicle.googleapis.com:8000" + ) + + +@pytest.mark.parametrize( + "transport_name", + [ + "rest", + ], +) +def test_rule_execution_error_service_client_transport_session_collision( + transport_name, +): + creds1 = ga_credentials.AnonymousCredentials() + creds2 = ga_credentials.AnonymousCredentials() + client1 = RuleExecutionErrorServiceClient( + credentials=creds1, + transport=transport_name, + ) + client2 = RuleExecutionErrorServiceClient( + credentials=creds2, + transport=transport_name, + ) + session1 = client1.transport.list_rule_execution_errors._session + session2 = client2.transport.list_rule_execution_errors._session + assert session1 != session2 + + +def test_rule_execution_error_service_grpc_transport_channel(): + channel = grpc.secure_channel("http://localhost/", grpc.local_channel_credentials()) + + # Check that channel is used if provided. + transport = transports.RuleExecutionErrorServiceGrpcTransport( + 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_rule_execution_error_service_grpc_asyncio_transport_channel(): + channel = aio.secure_channel("http://localhost/", grpc.local_channel_credentials()) + + # Check that channel is used if provided. + transport = transports.RuleExecutionErrorServiceGrpcAsyncIOTransport( + 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.filterwarnings("ignore::FutureWarning") +@pytest.mark.parametrize( + "transport_class", + [ + transports.RuleExecutionErrorServiceGrpcTransport, + transports.RuleExecutionErrorServiceGrpcAsyncIOTransport, + ], +) +def test_rule_execution_error_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.RuleExecutionErrorServiceGrpcTransport, + transports.RuleExecutionErrorServiceGrpcAsyncIOTransport, + ], +) +def test_rule_execution_error_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_curated_rule_path(): + project = "squid" + location = "clam" + instance = "whelk" + curatedRule = "octopus" + expected = "projects/{project}/locations/{location}/instances/{instance}/curatedRules/{curatedRule}".format( + project=project, + location=location, + instance=instance, + curatedRule=curatedRule, + ) + actual = RuleExecutionErrorServiceClient.curated_rule_path( + project, location, instance, curatedRule + ) + assert expected == actual + + +def test_parse_curated_rule_path(): + expected = { + "project": "oyster", + "location": "nudibranch", + "instance": "cuttlefish", + "curatedRule": "mussel", + } + path = RuleExecutionErrorServiceClient.curated_rule_path(**expected) + + # Check that the path construction is reversible. + actual = RuleExecutionErrorServiceClient.parse_curated_rule_path(path) + assert expected == actual + + +def test_rule_path(): + project = "winkle" + location = "nautilus" + instance = "scallop" + rule = "abalone" + expected = "projects/{project}/locations/{location}/instances/{instance}/rules/{rule}".format( + project=project, + location=location, + instance=instance, + rule=rule, + ) + actual = RuleExecutionErrorServiceClient.rule_path( + project, location, instance, rule + ) + assert expected == actual + + +def test_parse_rule_path(): + expected = { + "project": "squid", + "location": "clam", + "instance": "whelk", + "rule": "octopus", + } + path = RuleExecutionErrorServiceClient.rule_path(**expected) + + # Check that the path construction is reversible. + actual = RuleExecutionErrorServiceClient.parse_rule_path(path) + assert expected == actual + + +def test_rule_execution_error_path(): + project = "oyster" + location = "nudibranch" + instance = "cuttlefish" + rule_execution_error = "mussel" + expected = "projects/{project}/locations/{location}/instances/{instance}/ruleExecutionErrors/{rule_execution_error}".format( + project=project, + location=location, + instance=instance, + rule_execution_error=rule_execution_error, + ) + actual = RuleExecutionErrorServiceClient.rule_execution_error_path( + project, location, instance, rule_execution_error + ) + assert expected == actual + + +def test_parse_rule_execution_error_path(): + expected = { + "project": "winkle", + "location": "nautilus", + "instance": "scallop", + "rule_execution_error": "abalone", + } + path = RuleExecutionErrorServiceClient.rule_execution_error_path(**expected) + + # Check that the path construction is reversible. + actual = RuleExecutionErrorServiceClient.parse_rule_execution_error_path(path) + assert expected == actual + + +def test_common_billing_account_path(): + billing_account = "squid" + expected = "billingAccounts/{billing_account}".format( + billing_account=billing_account, + ) + actual = RuleExecutionErrorServiceClient.common_billing_account_path( + billing_account + ) + assert expected == actual + + +def test_parse_common_billing_account_path(): + expected = { + "billing_account": "clam", + } + path = RuleExecutionErrorServiceClient.common_billing_account_path(**expected) + + # Check that the path construction is reversible. + actual = RuleExecutionErrorServiceClient.parse_common_billing_account_path(path) + assert expected == actual + + +def test_common_folder_path(): + folder = "whelk" + expected = "folders/{folder}".format( + folder=folder, + ) + actual = RuleExecutionErrorServiceClient.common_folder_path(folder) + assert expected == actual + + +def test_parse_common_folder_path(): + expected = { + "folder": "octopus", + } + path = RuleExecutionErrorServiceClient.common_folder_path(**expected) + + # Check that the path construction is reversible. + actual = RuleExecutionErrorServiceClient.parse_common_folder_path(path) + assert expected == actual + + +def test_common_organization_path(): + organization = "oyster" + expected = "organizations/{organization}".format( + organization=organization, + ) + actual = RuleExecutionErrorServiceClient.common_organization_path(organization) + assert expected == actual + + +def test_parse_common_organization_path(): + expected = { + "organization": "nudibranch", + } + path = RuleExecutionErrorServiceClient.common_organization_path(**expected) + + # Check that the path construction is reversible. + actual = RuleExecutionErrorServiceClient.parse_common_organization_path(path) + assert expected == actual + + +def test_common_project_path(): + project = "cuttlefish" + expected = "projects/{project}".format( + project=project, + ) + actual = RuleExecutionErrorServiceClient.common_project_path(project) + assert expected == actual + + +def test_parse_common_project_path(): + expected = { + "project": "mussel", + } + path = RuleExecutionErrorServiceClient.common_project_path(**expected) + + # Check that the path construction is reversible. + actual = RuleExecutionErrorServiceClient.parse_common_project_path(path) + assert expected == actual + + +def test_common_location_path(): + project = "winkle" + location = "nautilus" + expected = "projects/{project}/locations/{location}".format( + project=project, + location=location, + ) + actual = RuleExecutionErrorServiceClient.common_location_path(project, location) + assert expected == actual + + +def test_parse_common_location_path(): + expected = { + "project": "scallop", + "location": "abalone", + } + path = RuleExecutionErrorServiceClient.common_location_path(**expected) + + # Check that the path construction is reversible. + actual = RuleExecutionErrorServiceClient.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.RuleExecutionErrorServiceTransport, "_prep_wrapped_messages" + ) as prep: + client = RuleExecutionErrorServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + client_info=client_info, + ) + prep.assert_called_once_with(client_info) + + with mock.patch.object( + transports.RuleExecutionErrorServiceTransport, "_prep_wrapped_messages" + ) as prep: + transport_class = RuleExecutionErrorServiceClient.get_transport_class() + transport = transport_class( + credentials=ga_credentials.AnonymousCredentials(), + client_info=client_info, + ) + prep.assert_called_once_with(client_info) + + +def test_delete_operation(transport: str = "grpc"): + client = RuleExecutionErrorServiceClient( + 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.DeleteOperationRequest() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.delete_operation), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = None + response = client.delete_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 response is None + + +@pytest.mark.asyncio +async def test_delete_operation_async(transport: str = "grpc_asyncio"): + client = RuleExecutionErrorServiceAsyncClient( + credentials=async_anonymous_credentials(), + 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.DeleteOperationRequest() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.delete_operation), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(None) + response = await client.delete_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 response is None + + +def test_delete_operation_field_headers(): + client = RuleExecutionErrorServiceClient( + 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.DeleteOperationRequest() + request.name = "locations" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.delete_operation), "__call__") as call: + call.return_value = None + + client.delete_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_delete_operation_field_headers_async(): + client = RuleExecutionErrorServiceAsyncClient( + credentials=async_anonymous_credentials(), + ) + + # 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.DeleteOperationRequest() + request.name = "locations" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.delete_operation), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(None) + await client.delete_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_delete_operation_from_dict(): + client = RuleExecutionErrorServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.delete_operation), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = None + + response = client.delete_operation( + request={ + "name": "locations", + } + ) + call.assert_called() + + +@pytest.mark.asyncio +async def test_delete_operation_from_dict_async(): + client = RuleExecutionErrorServiceAsyncClient( + credentials=async_anonymous_credentials(), + ) + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.delete_operation), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(None) + response = await client.delete_operation( + request={ + "name": "locations", + } + ) + call.assert_called() + + +def test_delete_operation_flattened(): + client = RuleExecutionErrorServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.delete_operation), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = None + + client.delete_operation() + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == operations_pb2.DeleteOperationRequest() + + +@pytest.mark.asyncio +async def test_delete_operation_flattened_async(): + client = RuleExecutionErrorServiceAsyncClient( + credentials=async_anonymous_credentials(), + ) + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.delete_operation), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(None) + await client.delete_operation() + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == operations_pb2.DeleteOperationRequest() + + +def test_cancel_operation(transport: str = "grpc"): + client = RuleExecutionErrorServiceClient( + 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.CancelOperationRequest() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.cancel_operation), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = None + response = client.cancel_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 response is None + + +@pytest.mark.asyncio +async def test_cancel_operation_async(transport: str = "grpc_asyncio"): + client = RuleExecutionErrorServiceAsyncClient( + credentials=async_anonymous_credentials(), + 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.CancelOperationRequest() + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.cancel_operation), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(None) + response = await client.cancel_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 response is None + + +def test_cancel_operation_field_headers(): + client = RuleExecutionErrorServiceClient( + 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.CancelOperationRequest() + request.name = "locations" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.cancel_operation), "__call__") as call: + call.return_value = None + + client.cancel_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_cancel_operation_field_headers_async(): + client = RuleExecutionErrorServiceAsyncClient( + credentials=async_anonymous_credentials(), + ) + + # 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.CancelOperationRequest() + request.name = "locations" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.cancel_operation), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(None) + await client.cancel_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_cancel_operation_from_dict(): + client = RuleExecutionErrorServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.cancel_operation), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = None + + response = client.cancel_operation( + request={ + "name": "locations", + } + ) + call.assert_called() + + +@pytest.mark.asyncio +async def test_cancel_operation_from_dict_async(): + client = RuleExecutionErrorServiceAsyncClient( + credentials=async_anonymous_credentials(), + ) + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.cancel_operation), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(None) + response = await client.cancel_operation( + request={ + "name": "locations", + } + ) + call.assert_called() + + +def test_cancel_operation_flattened(): + client = RuleExecutionErrorServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.cancel_operation), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = None + + client.cancel_operation() + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == operations_pb2.CancelOperationRequest() + + +@pytest.mark.asyncio +async def test_cancel_operation_flattened_async(): + client = RuleExecutionErrorServiceAsyncClient( + credentials=async_anonymous_credentials(), + ) + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.cancel_operation), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall(None) + await client.cancel_operation() + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == operations_pb2.CancelOperationRequest() + + +def test_get_operation(transport: str = "grpc"): + client = RuleExecutionErrorServiceClient( + 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 = RuleExecutionErrorServiceAsyncClient( + credentials=async_anonymous_credentials(), + 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 = RuleExecutionErrorServiceClient( + 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 = RuleExecutionErrorServiceAsyncClient( + credentials=async_anonymous_credentials(), + ) + + # 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 = RuleExecutionErrorServiceClient( + 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 = RuleExecutionErrorServiceAsyncClient( + credentials=async_anonymous_credentials(), + ) + # 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_get_operation_flattened(): + client = RuleExecutionErrorServiceClient( + 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() + + client.get_operation() + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == operations_pb2.GetOperationRequest() + + +@pytest.mark.asyncio +async def test_get_operation_flattened_async(): + client = RuleExecutionErrorServiceAsyncClient( + credentials=async_anonymous_credentials(), + ) + # 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() + ) + await client.get_operation() + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == operations_pb2.GetOperationRequest() + + +def test_list_operations(transport: str = "grpc"): + client = RuleExecutionErrorServiceClient( + 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 = RuleExecutionErrorServiceAsyncClient( + credentials=async_anonymous_credentials(), + 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 = RuleExecutionErrorServiceClient( + 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 = RuleExecutionErrorServiceAsyncClient( + credentials=async_anonymous_credentials(), + ) + + # 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 = RuleExecutionErrorServiceClient( + 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 = RuleExecutionErrorServiceAsyncClient( + credentials=async_anonymous_credentials(), + ) + # 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_list_operations_flattened(): + client = RuleExecutionErrorServiceClient( + 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() + + client.list_operations() + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == operations_pb2.ListOperationsRequest() + + +@pytest.mark.asyncio +async def test_list_operations_flattened_async(): + client = RuleExecutionErrorServiceAsyncClient( + credentials=async_anonymous_credentials(), + ) + # 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() + ) + await client.list_operations() + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + assert args[0] == operations_pb2.ListOperationsRequest() + + +def test_transport_close_grpc(): + client = RuleExecutionErrorServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="grpc" + ) + with mock.patch.object( + type(getattr(client.transport, "_grpc_channel")), "close" + ) as close: + with client: + close.assert_not_called() + close.assert_called_once() + + +@pytest.mark.asyncio +async def test_transport_close_grpc_asyncio(): + client = RuleExecutionErrorServiceAsyncClient( + credentials=async_anonymous_credentials(), transport="grpc_asyncio" + ) + with mock.patch.object( + type(getattr(client.transport, "_grpc_channel")), "close" + ) as close: + async with client: + close.assert_not_called() + close.assert_called_once() + + +def test_transport_close_rest(): + client = RuleExecutionErrorServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + with mock.patch.object( + type(getattr(client.transport, "_session")), "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 = RuleExecutionErrorServiceClient( + 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", + [ + ( + RuleExecutionErrorServiceClient, + transports.RuleExecutionErrorServiceGrpcTransport, + ), + ( + RuleExecutionErrorServiceAsyncClient, + transports.RuleExecutionErrorServiceGrpcAsyncIOTransport, + ), + ], +) +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-chronicle/tests/unit/gapic/chronicle_v1/test_rule_service.py b/packages/google-cloud-chronicle/tests/unit/gapic/chronicle_v1/test_rule_service.py index 699fba4cebd9..f5dda5f4378f 100644 --- a/packages/google-cloud-chronicle/tests/unit/gapic/chronicle_v1/test_rule_service.py +++ b/packages/google-cloud-chronicle/tests/unit/gapic/chronicle_v1/test_rule_service.py @@ -1283,7 +1283,11 @@ def test_rule_service_client_create_channel_credentials_file( credentials=file_creds, credentials_file=None, quota_project_id=None, - default_scopes=("https://www.googleapis.com/auth/cloud-platform",), + default_scopes=( + "https://www.googleapis.com/auth/chronicle", + "https://www.googleapis.com/auth/chronicle.readonly", + "https://www.googleapis.com/auth/cloud-platform", + ), scopes=None, default_host="chronicle.googleapis.com", ssl_credentials=None, @@ -3228,6 +3232,344 @@ async def test_delete_rule_flattened_error_async(): ) +@pytest.mark.parametrize( + "request_type", + [ + rule.VerifyRuleTextRequest(), + {}, + ], +) +def test_verify_rule_text(request_type, transport: str = "grpc"): + client = RuleServiceClient( + 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.verify_rule_text), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = rule.VerifyRuleTextResponse( + success=True, + ) + response = client.verify_rule_text(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = rule.VerifyRuleTextRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, rule.VerifyRuleTextResponse) + assert response.success is True + + +def test_verify_rule_text_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 = RuleServiceClient( + 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 = rule.VerifyRuleTextRequest( + instance="instance_value", + rule_text="rule_text_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.verify_rule_text), "__call__") as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.verify_rule_text(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + request_msg = rule.VerifyRuleTextRequest( + instance="instance_value", + rule_text="rule_text_value", + ) + assert args[0] == request_msg + + +def test_verify_rule_text_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = RuleServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.verify_rule_text in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.verify_rule_text] = ( + mock_rpc + ) + request = {} + client.verify_rule_text(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.verify_rule_text(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_verify_rule_text_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = RuleServiceAsyncClient( + credentials=async_anonymous_credentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.verify_rule_text + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.AsyncMock() + mock_rpc.return_value = mock.Mock() + client._client._transport._wrapped_methods[ + client._client._transport.verify_rule_text + ] = mock_rpc + + request = {} + await client.verify_rule_text(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + await client.verify_rule_text(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +@pytest.mark.parametrize( + "request_type", + [ + rule.VerifyRuleTextRequest(), + {}, + ], +) +async def test_verify_rule_text_async(request_type, transport: str = "grpc_asyncio"): + client = RuleServiceAsyncClient( + credentials=async_anonymous_credentials(), + 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.verify_rule_text), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + rule.VerifyRuleTextResponse( + success=True, + ) + ) + response = await client.verify_rule_text(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = rule.VerifyRuleTextRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, rule.VerifyRuleTextResponse) + assert response.success is True + + +def test_verify_rule_text_field_headers(): + client = RuleServiceClient( + 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 = rule.VerifyRuleTextRequest() + + request.instance = "instance_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.verify_rule_text), "__call__") as call: + call.return_value = rule.VerifyRuleTextResponse() + client.verify_rule_text(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", + "instance=instance_value", + ) in kw["metadata"] + + +@pytest.mark.asyncio +async def test_verify_rule_text_field_headers_async(): + client = RuleServiceAsyncClient( + credentials=async_anonymous_credentials(), + ) + + # 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 = rule.VerifyRuleTextRequest() + + request.instance = "instance_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.verify_rule_text), "__call__") as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + rule.VerifyRuleTextResponse() + ) + await client.verify_rule_text(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", + "instance=instance_value", + ) in kw["metadata"] + + +def test_verify_rule_text_flattened(): + client = RuleServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.verify_rule_text), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = rule.VerifyRuleTextResponse() + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + client.verify_rule_text( + instance="instance_value", + rule_text="rule_text_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].instance + mock_val = "instance_value" + assert arg == mock_val + arg = args[0].rule_text + mock_val = "rule_text_value" + assert arg == mock_val + + +def test_verify_rule_text_flattened_error(): + client = RuleServiceClient( + 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.verify_rule_text( + rule.VerifyRuleTextRequest(), + instance="instance_value", + rule_text="rule_text_value", + ) + + +@pytest.mark.asyncio +async def test_verify_rule_text_flattened_async(): + client = RuleServiceAsyncClient( + credentials=async_anonymous_credentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object(type(client.transport.verify_rule_text), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = rule.VerifyRuleTextResponse() + + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + rule.VerifyRuleTextResponse() + ) + # Call the method with a truthy value for each flattened field, + # using the keyword arguments to the method. + response = await client.verify_rule_text( + instance="instance_value", + rule_text="rule_text_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].instance + mock_val = "instance_value" + assert arg == mock_val + arg = args[0].rule_text + mock_val = "rule_text_value" + assert arg == mock_val + + +@pytest.mark.asyncio +async def test_verify_rule_text_flattened_error_async(): + client = RuleServiceAsyncClient( + credentials=async_anonymous_credentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + await client.verify_rule_text( + rule.VerifyRuleTextRequest(), + instance="instance_value", + rule_text="rule_text_value", + ) + + @pytest.mark.parametrize( "request_type", [ @@ -7119,8 +7461,187 @@ def test_delete_rule_rest_required_fields(request_type=rule.DeleteRuleRequest): 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 "name" in jsonified_request + assert jsonified_request["name"] == "name_value" + + client = RuleServiceClient( + 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 + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + + response = client.delete_rule(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert sorted(expected_params) == sorted(actual_params) + + +def test_delete_rule_rest_unset_required_fields(): + transport = transports.RuleServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.delete_rule._get_unset_required_fields({}) + assert set(unset_fields) == (set(("force",)) & set(("name",))) + + +def test_delete_rule_rest_flattened(): + client = RuleServiceClient( + 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/instances/sample3/rules/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 + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + + client.delete_rule(**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/{name=projects/*/locations/*/instances/*/rules/*}" + % client.transport._host, + args[1], + ) + + +def test_delete_rule_rest_flattened_error(transport: str = "rest"): + client = RuleServiceClient( + 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_rule( + rule.DeleteRuleRequest(), + name="name_value", + ) + + +def test_verify_rule_text_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = RuleServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert client._transport.verify_rule_text in client._transport._wrapped_methods + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.verify_rule_text] = ( + mock_rpc + ) + + request = {} + client.verify_rule_text(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + client.verify_rule_text(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_verify_rule_text_rest_required_fields(request_type=rule.VerifyRuleTextRequest): + transport_class = transports.RuleServiceRestTransport + + request_init = {} + request_init["instance"] = "" + request_init["rule_text"] = "" + 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() + ).verify_rule_text._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with default values are now present + + jsonified_request["instance"] = "instance_value" + jsonified_request["ruleText"] = "rule_text_value" + + unset_fields = transport_class( + credentials=ga_credentials.AnonymousCredentials() + ).verify_rule_text._get_unset_required_fields(jsonified_request) + jsonified_request.update(unset_fields) + + # verify required fields with non-default values are left alone + assert "instance" in jsonified_request + assert jsonified_request["instance"] == "instance_value" + assert "ruleText" in jsonified_request + assert jsonified_request["ruleText"] == "rule_text_value" client = RuleServiceClient( credentials=ga_credentials.AnonymousCredentials(), @@ -7129,7 +7650,7 @@ def test_delete_rule_rest_required_fields(request_type=rule.DeleteRuleRequest): request = request_type(**request_init) # Designate an appropriate value for the returned response. - return_value = None + return_value = rule.VerifyRuleTextResponse() # 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 @@ -7141,36 +7662,48 @@ def test_delete_rule_rest_required_fields(request_type=rule.DeleteRuleRequest): pb_request = request_type.pb(request) transcode_result = { "uri": "v1/sample_method", - "method": "delete", + "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 = "" + + # Convert return value to protobuf type + return_value = rule.VerifyRuleTextResponse.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 req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} - response = client.delete_rule(request) + response = client.verify_rule_text(request) expected_params = [("$alt", "json;enum-encoding=int")] actual_params = req.call_args.kwargs["params"] assert sorted(expected_params) == sorted(actual_params) -def test_delete_rule_rest_unset_required_fields(): +def test_verify_rule_text_rest_unset_required_fields(): transport = transports.RuleServiceRestTransport( credentials=ga_credentials.AnonymousCredentials ) - unset_fields = transport.delete_rule._get_unset_required_fields({}) - assert set(unset_fields) == (set(("force",)) & set(("name",))) + unset_fields = transport.verify_rule_text._get_unset_required_fields({}) + assert set(unset_fields) == ( + set(()) + & set( + ( + "instance", + "ruleText", + ) + ) + ) -def test_delete_rule_rest_flattened(): +def test_verify_rule_text_rest_flattened(): client = RuleServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest", @@ -7179,41 +7712,44 @@ def test_delete_rule_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 = None + return_value = rule.VerifyRuleTextResponse() # get arguments that satisfy an http rule for this method sample_request = { - "name": "projects/sample1/locations/sample2/instances/sample3/rules/sample4" + "instance": "projects/sample1/locations/sample2/instances/sample3" } # get truthy value for each flattened field mock_args = dict( - name="name_value", + instance="instance_value", + rule_text="rule_text_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 = "" + # Convert return value to protobuf type + return_value = rule.VerifyRuleTextResponse.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 req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} - client.delete_rule(**mock_args) + client.verify_rule_text(**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/{name=projects/*/locations/*/instances/*/rules/*}" + "%s/v1/{instance=projects/*/locations/*/instances/*}:verifyRuleText" % client.transport._host, args[1], ) -def test_delete_rule_rest_flattened_error(transport: str = "rest"): +def test_verify_rule_text_rest_flattened_error(transport: str = "rest"): client = RuleServiceClient( credentials=ga_credentials.AnonymousCredentials(), transport=transport, @@ -7222,9 +7758,10 @@ def test_delete_rule_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_rule( - rule.DeleteRuleRequest(), - name="name_value", + client.verify_rule_text( + rule.VerifyRuleTextRequest(), + instance="instance_value", + rule_text="rule_text_value", ) @@ -8970,6 +9507,26 @@ def test_delete_rule_empty_call_grpc(): assert args[0] == request_msg +# This test is a coverage failsafe to make sure that totally empty calls, +# i.e. request == None and no flattened fields passed, work. +def test_verify_rule_text_empty_call_grpc(): + client = RuleServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Mock the actual call, and fake the request. + with mock.patch.object(type(client.transport.verify_rule_text), "__call__") as call: + call.return_value = rule.VerifyRuleTextResponse() + client.verify_rule_text(request=None) + + # Establish that the underlying stub method was called. + call.assert_called() + _, args, _ = call.mock_calls[0] + request_msg = rule.VerifyRuleTextRequest() + assert args[0] == request_msg + + # This test is a coverage failsafe to make sure that totally empty calls, # i.e. request == None and no flattened fields passed, work. def test_list_rule_revisions_empty_call_grpc(): @@ -9291,6 +9848,32 @@ async def test_delete_rule_empty_call_grpc_asyncio(): assert args[0] == request_msg +# This test is a coverage failsafe to make sure that totally empty calls, +# i.e. request == None and no flattened fields passed, work. +@pytest.mark.asyncio +async def test_verify_rule_text_empty_call_grpc_asyncio(): + client = RuleServiceAsyncClient( + credentials=async_anonymous_credentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call, and fake the request. + with mock.patch.object(type(client.transport.verify_rule_text), "__call__") as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + rule.VerifyRuleTextResponse( + success=True, + ) + ) + await client.verify_rule_text(request=None) + + # Establish that the underlying stub method was called. + call.assert_called() + _, args, _ = call.mock_calls[0] + request_msg = rule.VerifyRuleTextRequest() + assert args[0] == request_msg + + # This test is a coverage failsafe to make sure that totally empty calls, # i.e. request == None and no flattened fields passed, work. @pytest.mark.asyncio @@ -10390,6 +10973,134 @@ def test_delete_rule_rest_interceptors(null_interceptor): pre.assert_called_once() +def test_verify_rule_text_rest_bad_request(request_type=rule.VerifyRuleTextRequest): + client = RuleServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + # send a request that will satisfy transcoding + request_init = {"instance": "projects/sample1/locations/sample2/instances/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 = mock.Mock() + json_return_value = "" + response_value.json = mock.Mock(return_value={}) + response_value.status_code = 400 + response_value.request = mock.Mock() + req.return_value = response_value + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + client.verify_rule_text(request) + + +@pytest.mark.parametrize( + "request_type", + [ + rule.VerifyRuleTextRequest, + dict, + ], +) +def test_verify_rule_text_rest_call_success(request_type): + client = RuleServiceClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + # send a request that will satisfy transcoding + request_init = {"instance": "projects/sample1/locations/sample2/instances/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 = rule.VerifyRuleTextResponse( + success=True, + ) + + # Wrap the value into a proper Response obj + response_value = mock.Mock() + response_value.status_code = 200 + + # Convert return value to protobuf type + return_value = rule.VerifyRuleTextResponse.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 + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + response = client.verify_rule_text(request) + + # Establish that the response is the type that we expect. + assert isinstance(response, rule.VerifyRuleTextResponse) + assert response.success is True + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_verify_rule_text_rest_interceptors(null_interceptor): + transport = transports.RuleServiceRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None + if null_interceptor + else transports.RuleServiceRestInterceptor(), + ) + client = RuleServiceClient(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.RuleServiceRestInterceptor, "post_verify_rule_text" + ) as post, + mock.patch.object( + transports.RuleServiceRestInterceptor, "post_verify_rule_text_with_metadata" + ) as post_with_metadata, + mock.patch.object( + transports.RuleServiceRestInterceptor, "pre_verify_rule_text" + ) as pre, + ): + pre.assert_not_called() + post.assert_not_called() + post_with_metadata.assert_not_called() + pb_message = rule.VerifyRuleTextRequest.pb(rule.VerifyRuleTextRequest()) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = mock.Mock() + req.return_value.status_code = 200 + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + return_value = rule.VerifyRuleTextResponse.to_json( + rule.VerifyRuleTextResponse() + ) + req.return_value.content = return_value + + request = rule.VerifyRuleTextRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = rule.VerifyRuleTextResponse() + post_with_metadata.return_value = rule.VerifyRuleTextResponse(), metadata + + client.verify_rule_text( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + post_with_metadata.assert_called_once() + + def test_list_rule_revisions_rest_bad_request( request_type=rule.ListRuleRevisionsRequest, ): @@ -11878,6 +12589,25 @@ def test_delete_rule_empty_call_rest(): assert args[0] == request_msg +# This test is a coverage failsafe to make sure that totally empty calls, +# i.e. request == None and no flattened fields passed, work. +def test_verify_rule_text_empty_call_rest(): + client = RuleServiceClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the actual call, and fake the request. + with mock.patch.object(type(client.transport.verify_rule_text), "__call__") as call: + client.verify_rule_text(request=None) + + # Establish that the underlying stub method was called. + call.assert_called() + _, args, _ = call.mock_calls[0] + request_msg = rule.VerifyRuleTextRequest() + assert args[0] == request_msg + + # This test is a coverage failsafe to make sure that totally empty calls, # i.e. request == None and no flattened fields passed, work. def test_list_rule_revisions_empty_call_rest(): @@ -12074,6 +12804,7 @@ def test_rule_service_base_transport(): "list_rules", "update_rule", "delete_rule", + "verify_rule_text", "list_rule_revisions", "create_retrohunt", "get_retrohunt", @@ -12126,7 +12857,11 @@ def test_rule_service_base_transport_with_credentials_file(): load_creds.assert_called_once_with( "credentials.json", scopes=None, - default_scopes=("https://www.googleapis.com/auth/cloud-platform",), + default_scopes=( + "https://www.googleapis.com/auth/chronicle", + "https://www.googleapis.com/auth/chronicle.readonly", + "https://www.googleapis.com/auth/cloud-platform", + ), quota_project_id="octopus", ) @@ -12152,7 +12887,11 @@ def test_rule_service_auth_adc(): RuleServiceClient() adc.assert_called_once_with( scopes=None, - default_scopes=("https://www.googleapis.com/auth/cloud-platform",), + default_scopes=( + "https://www.googleapis.com/auth/chronicle", + "https://www.googleapis.com/auth/chronicle.readonly", + "https://www.googleapis.com/auth/cloud-platform", + ), quota_project_id=None, ) @@ -12172,7 +12911,11 @@ def test_rule_service_transport_auth_adc(transport_class): 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",), + default_scopes=( + "https://www.googleapis.com/auth/chronicle", + "https://www.googleapis.com/auth/chronicle.readonly", + "https://www.googleapis.com/auth/cloud-platform", + ), quota_project_id="octopus", ) @@ -12225,7 +12968,11 @@ def test_rule_service_transport_create_channel(transport_class, grpc_helpers): credentials=creds, credentials_file=None, quota_project_id="octopus", - default_scopes=("https://www.googleapis.com/auth/cloud-platform",), + default_scopes=( + "https://www.googleapis.com/auth/chronicle", + "https://www.googleapis.com/auth/chronicle.readonly", + "https://www.googleapis.com/auth/cloud-platform", + ), scopes=["1", "2"], default_host="chronicle.googleapis.com", ssl_credentials=None, @@ -12367,6 +13114,9 @@ def test_rule_service_client_transport_session_collision(transport_name): session1 = client1.transport.delete_rule._session session2 = client2.transport.delete_rule._session assert session1 != session2 + session1 = client1.transport.verify_rule_text._session + session2 = client2.transport.verify_rule_text._session + assert session1 != session2 session1 = client1.transport.list_rule_revisions._session session2 = client2.transport.list_rule_revisions._session assert session1 != session2 @@ -12574,11 +13324,37 @@ def test_parse_data_access_scope_path(): assert expected == actual -def test_reference_list_path(): +def test_instance_path(): project = "winkle" location = "nautilus" instance = "scallop" - reference_list = "abalone" + expected = "projects/{project}/locations/{location}/instances/{instance}".format( + project=project, + location=location, + instance=instance, + ) + actual = RuleServiceClient.instance_path(project, location, instance) + assert expected == actual + + +def test_parse_instance_path(): + expected = { + "project": "abalone", + "location": "squid", + "instance": "clam", + } + path = RuleServiceClient.instance_path(**expected) + + # Check that the path construction is reversible. + actual = RuleServiceClient.parse_instance_path(path) + assert expected == actual + + +def test_reference_list_path(): + project = "whelk" + location = "octopus" + instance = "oyster" + reference_list = "nudibranch" expected = "projects/{project}/locations/{location}/instances/{instance}/referenceLists/{reference_list}".format( project=project, location=location, @@ -12593,10 +13369,10 @@ def test_reference_list_path(): def test_parse_reference_list_path(): expected = { - "project": "squid", - "location": "clam", - "instance": "whelk", - "reference_list": "octopus", + "project": "cuttlefish", + "location": "mussel", + "instance": "winkle", + "reference_list": "nautilus", } path = RuleServiceClient.reference_list_path(**expected) @@ -12606,11 +13382,11 @@ def test_parse_reference_list_path(): def test_retrohunt_path(): - project = "oyster" - location = "nudibranch" - instance = "cuttlefish" - rule = "mussel" - retrohunt = "winkle" + project = "scallop" + location = "abalone" + instance = "squid" + rule = "clam" + retrohunt = "whelk" expected = "projects/{project}/locations/{location}/instances/{instance}/rules/{rule}/retrohunts/{retrohunt}".format( project=project, location=location, @@ -12626,11 +13402,11 @@ def test_retrohunt_path(): def test_parse_retrohunt_path(): expected = { - "project": "nautilus", - "location": "scallop", - "instance": "abalone", - "rule": "squid", - "retrohunt": "clam", + "project": "octopus", + "location": "oyster", + "instance": "nudibranch", + "rule": "cuttlefish", + "retrohunt": "mussel", } path = RuleServiceClient.retrohunt_path(**expected) @@ -12640,10 +13416,10 @@ def test_parse_retrohunt_path(): def test_rule_path(): - project = "whelk" - location = "octopus" - instance = "oyster" - rule = "nudibranch" + project = "winkle" + location = "nautilus" + instance = "scallop" + rule = "abalone" expected = "projects/{project}/locations/{location}/instances/{instance}/rules/{rule}".format( project=project, location=location, @@ -12656,10 +13432,10 @@ def test_rule_path(): def test_parse_rule_path(): expected = { - "project": "cuttlefish", - "location": "mussel", - "instance": "winkle", - "rule": "nautilus", + "project": "squid", + "location": "clam", + "instance": "whelk", + "rule": "octopus", } path = RuleServiceClient.rule_path(**expected) @@ -12669,10 +13445,10 @@ def test_parse_rule_path(): def test_rule_deployment_path(): - project = "scallop" - location = "abalone" - instance = "squid" - rule = "clam" + project = "oyster" + location = "nudibranch" + instance = "cuttlefish" + rule = "mussel" expected = "projects/{project}/locations/{location}/instances/{instance}/rules/{rule}/deployment".format( project=project, location=location, @@ -12685,10 +13461,10 @@ def test_rule_deployment_path(): def test_parse_rule_deployment_path(): expected = { - "project": "whelk", - "location": "octopus", - "instance": "oyster", - "rule": "nudibranch", + "project": "winkle", + "location": "nautilus", + "instance": "scallop", + "rule": "abalone", } path = RuleServiceClient.rule_deployment_path(**expected) @@ -12698,7 +13474,7 @@ def test_parse_rule_deployment_path(): def test_common_billing_account_path(): - billing_account = "cuttlefish" + billing_account = "squid" expected = "billingAccounts/{billing_account}".format( billing_account=billing_account, ) @@ -12708,7 +13484,7 @@ def test_common_billing_account_path(): def test_parse_common_billing_account_path(): expected = { - "billing_account": "mussel", + "billing_account": "clam", } path = RuleServiceClient.common_billing_account_path(**expected) @@ -12718,7 +13494,7 @@ def test_parse_common_billing_account_path(): def test_common_folder_path(): - folder = "winkle" + folder = "whelk" expected = "folders/{folder}".format( folder=folder, ) @@ -12728,7 +13504,7 @@ def test_common_folder_path(): def test_parse_common_folder_path(): expected = { - "folder": "nautilus", + "folder": "octopus", } path = RuleServiceClient.common_folder_path(**expected) @@ -12738,7 +13514,7 @@ def test_parse_common_folder_path(): def test_common_organization_path(): - organization = "scallop" + organization = "oyster" expected = "organizations/{organization}".format( organization=organization, ) @@ -12748,7 +13524,7 @@ def test_common_organization_path(): def test_parse_common_organization_path(): expected = { - "organization": "abalone", + "organization": "nudibranch", } path = RuleServiceClient.common_organization_path(**expected) @@ -12758,7 +13534,7 @@ def test_parse_common_organization_path(): def test_common_project_path(): - project = "squid" + project = "cuttlefish" expected = "projects/{project}".format( project=project, ) @@ -12768,7 +13544,7 @@ def test_common_project_path(): def test_parse_common_project_path(): expected = { - "project": "clam", + "project": "mussel", } path = RuleServiceClient.common_project_path(**expected) @@ -12778,8 +13554,8 @@ def test_parse_common_project_path(): def test_common_location_path(): - project = "whelk" - location = "octopus" + project = "winkle" + location = "nautilus" expected = "projects/{project}/locations/{location}".format( project=project, location=location, @@ -12790,8 +13566,8 @@ def test_common_location_path(): def test_parse_common_location_path(): expected = { - "project": "oyster", - "location": "nudibranch", + "project": "scallop", + "location": "abalone", } path = RuleServiceClient.common_location_path(**expected) diff --git a/packages/google-cloud-dataform/google/cloud/dataform/__init__.py b/packages/google-cloud-dataform/google/cloud/dataform/__init__.py index a4034c27c505..289cec26608a 100644 --- a/packages/google-cloud-dataform/google/cloud/dataform/__init__.py +++ b/packages/google-cloud-dataform/google/cloud/dataform/__init__.py @@ -48,12 +48,19 @@ CreateWorkspaceRequest, DataEncryptionState, DeleteFolderRequest, + DeleteFolderTreeMetadata, + DeleteFolderTreeRequest, DeleteReleaseConfigRequest, + DeleteRepositoryLongRunningMetadata, + DeleteRepositoryLongRunningRequest, + DeleteRepositoryLongRunningResponse, DeleteRepositoryRequest, DeleteTeamFolderRequest, + DeleteTeamFolderTreeRequest, DeleteWorkflowConfigRequest, DeleteWorkflowInvocationRequest, DeleteWorkspaceRequest, + DirectoryContentsView, DirectoryEntry, DirectorySearchResult, FetchFileDiffRequest, @@ -67,6 +74,7 @@ FetchRepositoryHistoryRequest, FetchRepositoryHistoryResponse, FileSearchResult, + FilesystemEntryMetadata, Folder, GetCompilationResultRequest, GetConfigRequest, @@ -184,9 +192,15 @@ "CreateWorkspaceRequest", "DataEncryptionState", "DeleteFolderRequest", + "DeleteFolderTreeMetadata", + "DeleteFolderTreeRequest", "DeleteReleaseConfigRequest", + "DeleteRepositoryLongRunningMetadata", + "DeleteRepositoryLongRunningRequest", + "DeleteRepositoryLongRunningResponse", "DeleteRepositoryRequest", "DeleteTeamFolderRequest", + "DeleteTeamFolderTreeRequest", "DeleteWorkflowConfigRequest", "DeleteWorkflowInvocationRequest", "DeleteWorkspaceRequest", @@ -203,6 +217,7 @@ "FetchRepositoryHistoryRequest", "FetchRepositoryHistoryResponse", "FileSearchResult", + "FilesystemEntryMetadata", "Folder", "GetCompilationResultRequest", "GetConfigRequest", @@ -290,4 +305,5 @@ "Workspace", "WriteFileRequest", "WriteFileResponse", + "DirectoryContentsView", ) diff --git a/packages/google-cloud-dataform/google/cloud/dataform_v1beta1/__init__.py b/packages/google-cloud-dataform/google/cloud/dataform_v1beta1/__init__.py index 097c288f8006..8df970ab4a9b 100644 --- a/packages/google-cloud-dataform/google/cloud/dataform_v1beta1/__init__.py +++ b/packages/google-cloud-dataform/google/cloud/dataform_v1beta1/__init__.py @@ -50,12 +50,19 @@ CreateWorkspaceRequest, DataEncryptionState, DeleteFolderRequest, + DeleteFolderTreeMetadata, + DeleteFolderTreeRequest, DeleteReleaseConfigRequest, + DeleteRepositoryLongRunningMetadata, + DeleteRepositoryLongRunningRequest, + DeleteRepositoryLongRunningResponse, DeleteRepositoryRequest, DeleteTeamFolderRequest, + DeleteTeamFolderTreeRequest, DeleteWorkflowConfigRequest, DeleteWorkflowInvocationRequest, DeleteWorkspaceRequest, + DirectoryContentsView, DirectoryEntry, DirectorySearchResult, FetchFileDiffRequest, @@ -69,6 +76,7 @@ FetchRepositoryHistoryRequest, FetchRepositoryHistoryResponse, FileSearchResult, + FilesystemEntryMetadata, Folder, GetCompilationResultRequest, GetConfigRequest, @@ -269,12 +277,19 @@ def _get_version(dependency_name): "DataEncryptionState", "DataformClient", "DeleteFolderRequest", + "DeleteFolderTreeMetadata", + "DeleteFolderTreeRequest", "DeleteReleaseConfigRequest", + "DeleteRepositoryLongRunningMetadata", + "DeleteRepositoryLongRunningRequest", + "DeleteRepositoryLongRunningResponse", "DeleteRepositoryRequest", "DeleteTeamFolderRequest", + "DeleteTeamFolderTreeRequest", "DeleteWorkflowConfigRequest", "DeleteWorkflowInvocationRequest", "DeleteWorkspaceRequest", + "DirectoryContentsView", "DirectoryEntry", "DirectorySearchResult", "FetchFileDiffRequest", @@ -288,6 +303,7 @@ def _get_version(dependency_name): "FetchRepositoryHistoryRequest", "FetchRepositoryHistoryResponse", "FileSearchResult", + "FilesystemEntryMetadata", "Folder", "GetCompilationResultRequest", "GetConfigRequest", diff --git a/packages/google-cloud-dataform/google/cloud/dataform_v1beta1/gapic_metadata.json b/packages/google-cloud-dataform/google/cloud/dataform_v1beta1/gapic_metadata.json index 96580a73896c..d8e4662ff81a 100644 --- a/packages/google-cloud-dataform/google/cloud/dataform_v1beta1/gapic_metadata.json +++ b/packages/google-cloud-dataform/google/cloud/dataform_v1beta1/gapic_metadata.json @@ -75,6 +75,11 @@ "delete_folder" ] }, + "DeleteFolderTree": { + "methods": [ + "delete_folder_tree" + ] + }, "DeleteReleaseConfig": { "methods": [ "delete_release_config" @@ -85,11 +90,21 @@ "delete_repository" ] }, + "DeleteRepositoryLongRunning": { + "methods": [ + "delete_repository_long_running" + ] + }, "DeleteTeamFolder": { "methods": [ "delete_team_folder" ] }, + "DeleteTeamFolderTree": { + "methods": [ + "delete_team_folder_tree" + ] + }, "DeleteWorkflowConfig": { "methods": [ "delete_workflow_config" @@ -435,6 +450,11 @@ "delete_folder" ] }, + "DeleteFolderTree": { + "methods": [ + "delete_folder_tree" + ] + }, "DeleteReleaseConfig": { "methods": [ "delete_release_config" @@ -445,11 +465,21 @@ "delete_repository" ] }, + "DeleteRepositoryLongRunning": { + "methods": [ + "delete_repository_long_running" + ] + }, "DeleteTeamFolder": { "methods": [ "delete_team_folder" ] }, + "DeleteTeamFolderTree": { + "methods": [ + "delete_team_folder_tree" + ] + }, "DeleteWorkflowConfig": { "methods": [ "delete_workflow_config" @@ -795,6 +825,11 @@ "delete_folder" ] }, + "DeleteFolderTree": { + "methods": [ + "delete_folder_tree" + ] + }, "DeleteReleaseConfig": { "methods": [ "delete_release_config" @@ -805,11 +840,21 @@ "delete_repository" ] }, + "DeleteRepositoryLongRunning": { + "methods": [ + "delete_repository_long_running" + ] + }, "DeleteTeamFolder": { "methods": [ "delete_team_folder" ] }, + "DeleteTeamFolderTree": { + "methods": [ + "delete_team_folder_tree" + ] + }, "DeleteWorkflowConfig": { "methods": [ "delete_workflow_config" diff --git a/packages/google-cloud-dataform/google/cloud/dataform_v1beta1/services/dataform/async_client.py b/packages/google-cloud-dataform/google/cloud/dataform_v1beta1/services/dataform/async_client.py index 190f9add2f42..9c8047638a99 100644 --- a/packages/google-cloud-dataform/google/cloud/dataform_v1beta1/services/dataform/async_client.py +++ b/packages/google-cloud-dataform/google/cloud/dataform_v1beta1/services/dataform/async_client.py @@ -104,6 +104,10 @@ class DataformAsyncClient: ) folder_path = staticmethod(DataformClient.folder_path) parse_folder_path = staticmethod(DataformClient.parse_folder_path) + git_repository_link_path = staticmethod(DataformClient.git_repository_link_path) + parse_git_repository_link_path = staticmethod( + DataformClient.parse_git_repository_link_path + ) notebook_runtime_template_path = staticmethod( DataformClient.notebook_runtime_template_path ) @@ -803,6 +807,157 @@ async def sample_delete_team_folder(): metadata=metadata, ) + async def delete_team_folder_tree( + self, + request: Optional[Union[dataform.DeleteTeamFolderTreeRequest, dict]] = None, + *, + name: Optional[str] = None, + force: Optional[bool] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> operation_async.AsyncOperation: + r"""Deletes a TeamFolder with its contents (Folders, + Repositories, Workspaces, ReleaseConfigs, and + WorkflowConfigs). + + .. 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 dataform_v1beta1 + + async def sample_delete_team_folder_tree(): + # Create a client + client = dataform_v1beta1.DataformAsyncClient() + + # Initialize request argument(s) + request = dataform_v1beta1.DeleteTeamFolderTreeRequest( + name="name_value", + ) + + # Make the request + operation = await client.delete_team_folder_tree(request=request) + + print("Waiting for operation to complete...") + + response = await operation.result() + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.dataform_v1beta1.types.DeleteTeamFolderTreeRequest, dict]]): + The request object. ``DeleteTeamFolderTree`` request message. + name (:class:`str`): + Required. The TeamFolder's name. Format: + projects/{project}/locations/{location}/teamFolders/{team_folder} + + This corresponds to the ``name`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + force (:class:`bool`): + Optional. If ``false`` (default): The operation will + fail if any Repository within the folder hierarchy has + associated Release Configs or Workflow Configs. + + If ``true``: The operation will attempt to delete + everything, including any Release Configs and Workflow + Configs linked to Repositories within the folder + hierarchy. This permanently removes schedules and + resources. + + This corresponds to the ``force`` 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + google.api_core.operation_async.AsyncOperation: + An object representing a long-running operation. + + The result type for the operation will be :class:`google.protobuf.empty_pb2.Empty` A generic empty message that you can re-use to avoid defining duplicated + empty messages in your APIs. A typical example is to + use it as the request or the response type of an API + method. For instance: + + service Foo { + rpc Bar(google.protobuf.Empty) returns + (google.protobuf.Empty); + + } + + """ + # 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. + flattened_params = [name, force] + has_flattened_params = ( + len([param for param in flattened_params if param is not None]) > 0 + ) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, dataform.DeleteTeamFolderTreeRequest): + request = dataform.DeleteTeamFolderTreeRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if name is not None: + request.name = name + if force is not None: + request.force = force + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.delete_team_folder_tree + ] + + # 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, + empty_pb2.Empty, + metadata_type=dataform.DeleteFolderTreeMetadata, + ) + + # Done; return the response. + return response + async def query_team_folder_contents( self, request: Optional[Union[dataform.QueryTeamFolderContentsRequest, dict]] = None, @@ -845,8 +1000,9 @@ async def sample_query_team_folder_contents(): request (Optional[Union[google.cloud.dataform_v1beta1.types.QueryTeamFolderContentsRequest, dict]]): The request object. ``QueryTeamFolderContents`` request message. team_folder (:class:`str`): - Required. Name of the team_folder whose contents to - list. Format: ``projects/*/locations/*/teamFolders/*``. + Required. Resource name of the TeamFolder to list + contents for. Format: + ``projects/*/locations/*/teamFolders/*``. This corresponds to the ``team_folder`` field on the ``request`` instance; if ``request`` is provided, this @@ -1487,6 +1643,158 @@ async def sample_delete_folder(): metadata=metadata, ) + async def delete_folder_tree( + self, + request: Optional[Union[dataform.DeleteFolderTreeRequest, dict]] = None, + *, + name: Optional[str] = None, + force: Optional[bool] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> operation_async.AsyncOperation: + r"""Deletes a Folder with its contents (Folders, + Repositories, Workspaces, ReleaseConfigs, and + WorkflowConfigs). + + .. 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 dataform_v1beta1 + + async def sample_delete_folder_tree(): + # Create a client + client = dataform_v1beta1.DataformAsyncClient() + + # Initialize request argument(s) + request = dataform_v1beta1.DeleteFolderTreeRequest( + name="name_value", + ) + + # Make the request + operation = await client.delete_folder_tree(request=request) + + print("Waiting for operation to complete...") + + response = await operation.result() + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.dataform_v1beta1.types.DeleteFolderTreeRequest, dict]]): + The request object. ``DeleteFolderTree`` request message. + name (:class:`str`): + Required. The Folder's name. + Format: + projects/{project}/locations/{location}/folders/{folder} + + This corresponds to the ``name`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + force (:class:`bool`): + Optional. If ``false`` (default): The operation will + fail if any Repository within the folder hierarchy has + associated Release Configs or Workflow Configs. + + If ``true``: The operation will attempt to delete + everything, including any Release Configs and Workflow + Configs linked to Repositories within the folder + hierarchy. This permanently removes schedules and + resources. + + This corresponds to the ``force`` 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + google.api_core.operation_async.AsyncOperation: + An object representing a long-running operation. + + The result type for the operation will be :class:`google.protobuf.empty_pb2.Empty` A generic empty message that you can re-use to avoid defining duplicated + empty messages in your APIs. A typical example is to + use it as the request or the response type of an API + method. For instance: + + service Foo { + rpc Bar(google.protobuf.Empty) returns + (google.protobuf.Empty); + + } + + """ + # 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. + flattened_params = [name, force] + has_flattened_params = ( + len([param for param in flattened_params if param is not None]) > 0 + ) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, dataform.DeleteFolderTreeRequest): + request = dataform.DeleteFolderTreeRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if name is not None: + request.name = name + if force is not None: + request.force = force + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.delete_folder_tree + ] + + # 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, + empty_pb2.Empty, + metadata_type=dataform.DeleteFolderTreeMetadata, + ) + + # Done; return the response. + return response + async def query_folder_contents( self, request: Optional[Union[dataform.QueryFolderContentsRequest, dict]] = None, @@ -1529,8 +1837,8 @@ async def sample_query_folder_contents(): request (Optional[Union[google.cloud.dataform_v1beta1.types.QueryFolderContentsRequest, dict]]): The request object. ``QueryFolderContents`` request message. folder (:class:`str`): - Required. Name of the folder whose contents to list. - Format: projects/*/locations/*/folders/\* + Required. Resource name of the Folder to list contents + for. Format: projects/*/locations/*/folders/\* This corresponds to the ``folder`` field on the ``request`` instance; if ``request`` is provided, this @@ -1656,8 +1964,8 @@ async def sample_query_user_root_contents(): request (Optional[Union[google.cloud.dataform_v1beta1.types.QueryUserRootContentsRequest, dict]]): The request object. ``QueryUserRootContents`` request message. location (:class:`str`): - Required. Location of the user root folder whose - contents to list. Format: projects/*/locations/* + Required. Location of the user root folder to list + contents for. Format: projects/*/locations/* This corresponds to the ``location`` field on the ``request`` instance; if ``request`` is provided, this @@ -2469,6 +2777,149 @@ async def sample_delete_repository(): metadata=metadata, ) + async def delete_repository_long_running( + self, + request: Optional[ + Union[dataform.DeleteRepositoryLongRunningRequest, dict] + ] = None, + *, + name: Optional[str] = None, + force: Optional[bool] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> operation_async.AsyncOperation: + r"""Deletes a single repository asynchronously. + + .. 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 dataform_v1beta1 + + async def sample_delete_repository_long_running(): + # Create a client + client = dataform_v1beta1.DataformAsyncClient() + + # Initialize request argument(s) + request = dataform_v1beta1.DeleteRepositoryLongRunningRequest( + name="name_value", + ) + + # Make the request + operation = await client.delete_repository_long_running(request=request) + + print("Waiting for operation to complete...") + + response = await operation.result() + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.dataform_v1beta1.types.DeleteRepositoryLongRunningRequest, dict]]): + The request object. ``DeleteRepositoryLongRunning`` request message. + name (:class:`str`): + Required. The repository's name. + This corresponds to the ``name`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + force (:class:`bool`): + Optional. If set to true, child resources of this + repository (compilation results and workflow + invocations) will also be deleted. Otherwise, the + request will only succeed if the repository has no child + resources. + + **Note:** *This flag doesn't support deletion of + workspaces, release configs or workflow configs. If any + of such resources exists in the repository, the request + will fail.* + + This corresponds to the ``force`` 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + 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.dataform_v1beta1.types.DeleteRepositoryLongRunningResponse` + DeleteRepositoryLongRunning response message. + + """ + # 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. + flattened_params = [name, force] + has_flattened_params = ( + len([param for param in flattened_params if param is not None]) > 0 + ) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, dataform.DeleteRepositoryLongRunningRequest): + request = dataform.DeleteRepositoryLongRunningRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if name is not None: + request.name = name + if force is not None: + request.force = force + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.delete_repository_long_running + ] + + # 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, + dataform.DeleteRepositoryLongRunningResponse, + metadata_type=dataform.DeleteRepositoryLongRunningMetadata, + ) + + # Done; return the response. + return response + async def move_repository( self, request: Optional[Union[dataform.MoveRepositoryRequest, dict]] = None, diff --git a/packages/google-cloud-dataform/google/cloud/dataform_v1beta1/services/dataform/client.py b/packages/google-cloud-dataform/google/cloud/dataform_v1beta1/services/dataform/client.py index 191507732997..3338406c3ca9 100644 --- a/packages/google-cloud-dataform/google/cloud/dataform_v1beta1/services/dataform/client.py +++ b/packages/google-cloud-dataform/google/cloud/dataform_v1beta1/services/dataform/client.py @@ -358,6 +358,30 @@ def parse_folder_path(path: str) -> Dict[str, str]: ) return m.groupdict() if m else {} + @staticmethod + def git_repository_link_path( + project: str, + location: str, + connection: str, + git_repository_link: str, + ) -> str: + """Returns a fully-qualified git_repository_link string.""" + return "projects/{project}/locations/{location}/connections/{connection}/gitRepositoryLinks/{git_repository_link}".format( + project=project, + location=location, + connection=connection, + git_repository_link=git_repository_link, + ) + + @staticmethod + def parse_git_repository_link_path(path: str) -> Dict[str, str]: + """Parses a git_repository_link path into its component segments.""" + m = re.match( + r"^projects/(?P.+?)/locations/(?P.+?)/connections/(?P.+?)/gitRepositoryLinks/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + @staticmethod def notebook_runtime_template_path( project: str, @@ -1477,6 +1501,154 @@ def sample_delete_team_folder(): metadata=metadata, ) + def delete_team_folder_tree( + self, + request: Optional[Union[dataform.DeleteTeamFolderTreeRequest, dict]] = None, + *, + name: Optional[str] = None, + force: Optional[bool] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> operation.Operation: + r"""Deletes a TeamFolder with its contents (Folders, + Repositories, Workspaces, ReleaseConfigs, and + WorkflowConfigs). + + .. 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 dataform_v1beta1 + + def sample_delete_team_folder_tree(): + # Create a client + client = dataform_v1beta1.DataformClient() + + # Initialize request argument(s) + request = dataform_v1beta1.DeleteTeamFolderTreeRequest( + name="name_value", + ) + + # Make the request + operation = client.delete_team_folder_tree(request=request) + + print("Waiting for operation to complete...") + + response = operation.result() + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.dataform_v1beta1.types.DeleteTeamFolderTreeRequest, dict]): + The request object. ``DeleteTeamFolderTree`` request message. + name (str): + Required. The TeamFolder's name. Format: + projects/{project}/locations/{location}/teamFolders/{team_folder} + + This corresponds to the ``name`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + force (bool): + Optional. If ``false`` (default): The operation will + fail if any Repository within the folder hierarchy has + associated Release Configs or Workflow Configs. + + If ``true``: The operation will attempt to delete + everything, including any Release Configs and Workflow + Configs linked to Repositories within the folder + hierarchy. This permanently removes schedules and + resources. + + This corresponds to the ``force`` 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + google.api_core.operation.Operation: + An object representing a long-running operation. + + The result type for the operation will be :class:`google.protobuf.empty_pb2.Empty` A generic empty message that you can re-use to avoid defining duplicated + empty messages in your APIs. A typical example is to + use it as the request or the response type of an API + method. For instance: + + service Foo { + rpc Bar(google.protobuf.Empty) returns + (google.protobuf.Empty); + + } + + """ + # 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. + flattened_params = [name, force] + has_flattened_params = ( + len([param for param in flattened_params if param is not None]) > 0 + ) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, dataform.DeleteTeamFolderTreeRequest): + request = dataform.DeleteTeamFolderTreeRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if name is not None: + request.name = name + if force is not None: + request.force = force + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.delete_team_folder_tree] + + # 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, + empty_pb2.Empty, + metadata_type=dataform.DeleteFolderTreeMetadata, + ) + + # Done; return the response. + return response + def query_team_folder_contents( self, request: Optional[Union[dataform.QueryTeamFolderContentsRequest, dict]] = None, @@ -1519,8 +1691,9 @@ def sample_query_team_folder_contents(): request (Union[google.cloud.dataform_v1beta1.types.QueryTeamFolderContentsRequest, dict]): The request object. ``QueryTeamFolderContents`` request message. team_folder (str): - Required. Name of the team_folder whose contents to - list. Format: ``projects/*/locations/*/teamFolders/*``. + Required. Resource name of the TeamFolder to list + contents for. Format: + ``projects/*/locations/*/teamFolders/*``. This corresponds to the ``team_folder`` field on the ``request`` instance; if ``request`` is provided, this @@ -2146,6 +2319,155 @@ def sample_delete_folder(): metadata=metadata, ) + def delete_folder_tree( + self, + request: Optional[Union[dataform.DeleteFolderTreeRequest, dict]] = None, + *, + name: Optional[str] = None, + force: Optional[bool] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> operation.Operation: + r"""Deletes a Folder with its contents (Folders, + Repositories, Workspaces, ReleaseConfigs, and + WorkflowConfigs). + + .. 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 dataform_v1beta1 + + def sample_delete_folder_tree(): + # Create a client + client = dataform_v1beta1.DataformClient() + + # Initialize request argument(s) + request = dataform_v1beta1.DeleteFolderTreeRequest( + name="name_value", + ) + + # Make the request + operation = client.delete_folder_tree(request=request) + + print("Waiting for operation to complete...") + + response = operation.result() + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.dataform_v1beta1.types.DeleteFolderTreeRequest, dict]): + The request object. ``DeleteFolderTree`` request message. + name (str): + Required. The Folder's name. + Format: + projects/{project}/locations/{location}/folders/{folder} + + This corresponds to the ``name`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + force (bool): + Optional. If ``false`` (default): The operation will + fail if any Repository within the folder hierarchy has + associated Release Configs or Workflow Configs. + + If ``true``: The operation will attempt to delete + everything, including any Release Configs and Workflow + Configs linked to Repositories within the folder + hierarchy. This permanently removes schedules and + resources. + + This corresponds to the ``force`` 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + google.api_core.operation.Operation: + An object representing a long-running operation. + + The result type for the operation will be :class:`google.protobuf.empty_pb2.Empty` A generic empty message that you can re-use to avoid defining duplicated + empty messages in your APIs. A typical example is to + use it as the request or the response type of an API + method. For instance: + + service Foo { + rpc Bar(google.protobuf.Empty) returns + (google.protobuf.Empty); + + } + + """ + # 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. + flattened_params = [name, force] + has_flattened_params = ( + len([param for param in flattened_params if param is not None]) > 0 + ) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, dataform.DeleteFolderTreeRequest): + request = dataform.DeleteFolderTreeRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if name is not None: + request.name = name + if force is not None: + request.force = force + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.delete_folder_tree] + + # 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, + empty_pb2.Empty, + metadata_type=dataform.DeleteFolderTreeMetadata, + ) + + # Done; return the response. + return response + def query_folder_contents( self, request: Optional[Union[dataform.QueryFolderContentsRequest, dict]] = None, @@ -2188,8 +2510,8 @@ def sample_query_folder_contents(): request (Union[google.cloud.dataform_v1beta1.types.QueryFolderContentsRequest, dict]): The request object. ``QueryFolderContents`` request message. folder (str): - Required. Name of the folder whose contents to list. - Format: projects/*/locations/*/folders/\* + Required. Resource name of the Folder to list contents + for. Format: projects/*/locations/*/folders/\* This corresponds to the ``folder`` field on the ``request`` instance; if ``request`` is provided, this @@ -2312,8 +2634,8 @@ def sample_query_user_root_contents(): request (Union[google.cloud.dataform_v1beta1.types.QueryUserRootContentsRequest, dict]): The request object. ``QueryUserRootContents`` request message. location (str): - Required. Location of the user root folder whose - contents to list. Format: projects/*/locations/* + Required. Location of the user root folder to list + contents for. Format: projects/*/locations/* This corresponds to the ``location`` field on the ``request`` instance; if ``request`` is provided, this @@ -3104,6 +3426,148 @@ def sample_delete_repository(): metadata=metadata, ) + def delete_repository_long_running( + self, + request: Optional[ + Union[dataform.DeleteRepositoryLongRunningRequest, dict] + ] = None, + *, + name: Optional[str] = None, + force: Optional[bool] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> operation.Operation: + r"""Deletes a single repository asynchronously. + + .. 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 dataform_v1beta1 + + def sample_delete_repository_long_running(): + # Create a client + client = dataform_v1beta1.DataformClient() + + # Initialize request argument(s) + request = dataform_v1beta1.DeleteRepositoryLongRunningRequest( + name="name_value", + ) + + # Make the request + operation = client.delete_repository_long_running(request=request) + + print("Waiting for operation to complete...") + + response = operation.result() + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.dataform_v1beta1.types.DeleteRepositoryLongRunningRequest, dict]): + The request object. ``DeleteRepositoryLongRunning`` request message. + name (str): + Required. The repository's name. + This corresponds to the ``name`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + force (bool): + Optional. If set to true, child resources of this + repository (compilation results and workflow + invocations) will also be deleted. Otherwise, the + request will only succeed if the repository has no child + resources. + + **Note:** *This flag doesn't support deletion of + workspaces, release configs or workflow configs. If any + of such resources exists in the repository, the request + will fail.* + + This corresponds to the ``force`` 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + google.api_core.operation.Operation: + An object representing a long-running operation. + + The result type for the operation will be + :class:`google.cloud.dataform_v1beta1.types.DeleteRepositoryLongRunningResponse` + DeleteRepositoryLongRunning response message. + + """ + # 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. + flattened_params = [name, force] + has_flattened_params = ( + len([param for param in flattened_params if param is not None]) > 0 + ) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, dataform.DeleteRepositoryLongRunningRequest): + request = dataform.DeleteRepositoryLongRunningRequest(request) + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if name is not None: + request.name = name + if force is not None: + request.force = force + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[ + self._transport.delete_repository_long_running + ] + + # 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, + dataform.DeleteRepositoryLongRunningResponse, + metadata_type=dataform.DeleteRepositoryLongRunningMetadata, + ) + + # Done; return the response. + return response + def move_repository( self, request: Optional[Union[dataform.MoveRepositoryRequest, dict]] = None, diff --git a/packages/google-cloud-dataform/google/cloud/dataform_v1beta1/services/dataform/transports/base.py b/packages/google-cloud-dataform/google/cloud/dataform_v1beta1/services/dataform/transports/base.py index 800ce86e7956..544e265d0177 100644 --- a/packages/google-cloud-dataform/google/cloud/dataform_v1beta1/services/dataform/transports/base.py +++ b/packages/google-cloud-dataform/google/cloud/dataform_v1beta1/services/dataform/transports/base.py @@ -174,6 +174,11 @@ def _prep_wrapped_messages(self, client_info): default_timeout=None, client_info=client_info, ), + self.delete_team_folder_tree: gapic_v1.method.wrap_method( + self.delete_team_folder_tree, + default_timeout=None, + client_info=client_info, + ), self.query_team_folder_contents: gapic_v1.method.wrap_method( self.query_team_folder_contents, default_timeout=None, @@ -204,6 +209,11 @@ def _prep_wrapped_messages(self, client_info): default_timeout=None, client_info=client_info, ), + self.delete_folder_tree: gapic_v1.method.wrap_method( + self.delete_folder_tree, + default_timeout=None, + client_info=client_info, + ), self.query_folder_contents: gapic_v1.method.wrap_method( self.query_folder_contents, default_timeout=None, @@ -244,6 +254,11 @@ def _prep_wrapped_messages(self, client_info): default_timeout=None, client_info=client_info, ), + self.delete_repository_long_running: gapic_v1.method.wrap_method( + self.delete_repository_long_running, + default_timeout=None, + client_info=client_info, + ), self.move_repository: gapic_v1.method.wrap_method( self.move_repository, default_timeout=None, @@ -591,6 +606,15 @@ def delete_team_folder( ]: raise NotImplementedError() + @property + def delete_team_folder_tree( + self, + ) -> Callable[ + [dataform.DeleteTeamFolderTreeRequest], + Union[operations_pb2.Operation, Awaitable[operations_pb2.Operation]], + ]: + raise NotImplementedError() + @property def query_team_folder_contents( self, @@ -650,6 +674,15 @@ def delete_folder( ]: raise NotImplementedError() + @property + def delete_folder_tree( + self, + ) -> Callable[ + [dataform.DeleteFolderTreeRequest], + Union[operations_pb2.Operation, Awaitable[operations_pb2.Operation]], + ]: + raise NotImplementedError() + @property def query_folder_contents( self, @@ -731,6 +764,15 @@ def delete_repository( ]: raise NotImplementedError() + @property + def delete_repository_long_running( + self, + ) -> Callable[ + [dataform.DeleteRepositoryLongRunningRequest], + Union[operations_pb2.Operation, Awaitable[operations_pb2.Operation]], + ]: + raise NotImplementedError() + @property def move_repository( self, diff --git a/packages/google-cloud-dataform/google/cloud/dataform_v1beta1/services/dataform/transports/grpc.py b/packages/google-cloud-dataform/google/cloud/dataform_v1beta1/services/dataform/transports/grpc.py index a1d93fa743bc..bcc1e3f40018 100644 --- a/packages/google-cloud-dataform/google/cloud/dataform_v1beta1/services/dataform/transports/grpc.py +++ b/packages/google-cloud-dataform/google/cloud/dataform_v1beta1/services/dataform/transports/grpc.py @@ -457,6 +457,34 @@ def delete_team_folder( ) return self._stubs["delete_team_folder"] + @property + def delete_team_folder_tree( + self, + ) -> Callable[[dataform.DeleteTeamFolderTreeRequest], operations_pb2.Operation]: + r"""Return a callable for the delete team folder tree method over gRPC. + + Deletes a TeamFolder with its contents (Folders, + Repositories, Workspaces, ReleaseConfigs, and + WorkflowConfigs). + + Returns: + Callable[[~.DeleteTeamFolderTreeRequest], + ~.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 "delete_team_folder_tree" not in self._stubs: + self._stubs["delete_team_folder_tree"] = self._logged_channel.unary_unary( + "/google.cloud.dataform.v1beta1.Dataform/DeleteTeamFolderTree", + request_serializer=dataform.DeleteTeamFolderTreeRequest.serialize, + response_deserializer=operations_pb2.Operation.FromString, + ) + return self._stubs["delete_team_folder_tree"] + @property def query_team_folder_contents( self, @@ -619,6 +647,34 @@ def delete_folder( ) return self._stubs["delete_folder"] + @property + def delete_folder_tree( + self, + ) -> Callable[[dataform.DeleteFolderTreeRequest], operations_pb2.Operation]: + r"""Return a callable for the delete folder tree method over gRPC. + + Deletes a Folder with its contents (Folders, + Repositories, Workspaces, ReleaseConfigs, and + WorkflowConfigs). + + Returns: + Callable[[~.DeleteFolderTreeRequest], + ~.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 "delete_folder_tree" not in self._stubs: + self._stubs["delete_folder_tree"] = self._logged_channel.unary_unary( + "/google.cloud.dataform.v1beta1.Dataform/DeleteFolderTree", + request_serializer=dataform.DeleteFolderTreeRequest.serialize, + response_deserializer=operations_pb2.Operation.FromString, + ) + return self._stubs["delete_folder_tree"] + @property def query_folder_contents( self, @@ -848,6 +904,36 @@ def delete_repository( ) return self._stubs["delete_repository"] + @property + def delete_repository_long_running( + self, + ) -> Callable[ + [dataform.DeleteRepositoryLongRunningRequest], operations_pb2.Operation + ]: + r"""Return a callable for the delete repository long running method over gRPC. + + Deletes a single repository asynchronously. + + Returns: + Callable[[~.DeleteRepositoryLongRunningRequest], + ~.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 "delete_repository_long_running" not in self._stubs: + self._stubs["delete_repository_long_running"] = ( + self._logged_channel.unary_unary( + "/google.cloud.dataform.v1beta1.Dataform/DeleteRepositoryLongRunning", + request_serializer=dataform.DeleteRepositoryLongRunningRequest.serialize, + response_deserializer=operations_pb2.Operation.FromString, + ) + ) + return self._stubs["delete_repository_long_running"] + @property def move_repository( self, diff --git a/packages/google-cloud-dataform/google/cloud/dataform_v1beta1/services/dataform/transports/grpc_asyncio.py b/packages/google-cloud-dataform/google/cloud/dataform_v1beta1/services/dataform/transports/grpc_asyncio.py index 6878f533767a..31a0d441aa01 100644 --- a/packages/google-cloud-dataform/google/cloud/dataform_v1beta1/services/dataform/transports/grpc_asyncio.py +++ b/packages/google-cloud-dataform/google/cloud/dataform_v1beta1/services/dataform/transports/grpc_asyncio.py @@ -465,6 +465,36 @@ def delete_team_folder( ) return self._stubs["delete_team_folder"] + @property + def delete_team_folder_tree( + self, + ) -> Callable[ + [dataform.DeleteTeamFolderTreeRequest], Awaitable[operations_pb2.Operation] + ]: + r"""Return a callable for the delete team folder tree method over gRPC. + + Deletes a TeamFolder with its contents (Folders, + Repositories, Workspaces, ReleaseConfigs, and + WorkflowConfigs). + + Returns: + Callable[[~.DeleteTeamFolderTreeRequest], + 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 "delete_team_folder_tree" not in self._stubs: + self._stubs["delete_team_folder_tree"] = self._logged_channel.unary_unary( + "/google.cloud.dataform.v1beta1.Dataform/DeleteTeamFolderTree", + request_serializer=dataform.DeleteTeamFolderTreeRequest.serialize, + response_deserializer=operations_pb2.Operation.FromString, + ) + return self._stubs["delete_team_folder_tree"] + @property def query_team_folder_contents( self, @@ -630,6 +660,36 @@ def delete_folder( ) return self._stubs["delete_folder"] + @property + def delete_folder_tree( + self, + ) -> Callable[ + [dataform.DeleteFolderTreeRequest], Awaitable[operations_pb2.Operation] + ]: + r"""Return a callable for the delete folder tree method over gRPC. + + Deletes a Folder with its contents (Folders, + Repositories, Workspaces, ReleaseConfigs, and + WorkflowConfigs). + + Returns: + Callable[[~.DeleteFolderTreeRequest], + 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 "delete_folder_tree" not in self._stubs: + self._stubs["delete_folder_tree"] = self._logged_channel.unary_unary( + "/google.cloud.dataform.v1beta1.Dataform/DeleteFolderTree", + request_serializer=dataform.DeleteFolderTreeRequest.serialize, + response_deserializer=operations_pb2.Operation.FromString, + ) + return self._stubs["delete_folder_tree"] + @property def query_folder_contents( self, @@ -861,6 +921,37 @@ def delete_repository( ) return self._stubs["delete_repository"] + @property + def delete_repository_long_running( + self, + ) -> Callable[ + [dataform.DeleteRepositoryLongRunningRequest], + Awaitable[operations_pb2.Operation], + ]: + r"""Return a callable for the delete repository long running method over gRPC. + + Deletes a single repository asynchronously. + + Returns: + Callable[[~.DeleteRepositoryLongRunningRequest], + 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 "delete_repository_long_running" not in self._stubs: + self._stubs["delete_repository_long_running"] = ( + self._logged_channel.unary_unary( + "/google.cloud.dataform.v1beta1.Dataform/DeleteRepositoryLongRunning", + request_serializer=dataform.DeleteRepositoryLongRunningRequest.serialize, + response_deserializer=operations_pb2.Operation.FromString, + ) + ) + return self._stubs["delete_repository_long_running"] + @property def move_repository( self, @@ -2432,6 +2523,11 @@ def _prep_wrapped_messages(self, client_info): default_timeout=None, client_info=client_info, ), + self.delete_team_folder_tree: self._wrap_method( + self.delete_team_folder_tree, + default_timeout=None, + client_info=client_info, + ), self.query_team_folder_contents: self._wrap_method( self.query_team_folder_contents, default_timeout=None, @@ -2462,6 +2558,11 @@ def _prep_wrapped_messages(self, client_info): default_timeout=None, client_info=client_info, ), + self.delete_folder_tree: self._wrap_method( + self.delete_folder_tree, + default_timeout=None, + client_info=client_info, + ), self.query_folder_contents: self._wrap_method( self.query_folder_contents, default_timeout=None, @@ -2502,6 +2603,11 @@ def _prep_wrapped_messages(self, client_info): default_timeout=None, client_info=client_info, ), + self.delete_repository_long_running: self._wrap_method( + self.delete_repository_long_running, + default_timeout=None, + client_info=client_info, + ), self.move_repository: self._wrap_method( self.move_repository, default_timeout=None, diff --git a/packages/google-cloud-dataform/google/cloud/dataform_v1beta1/services/dataform/transports/rest.py b/packages/google-cloud-dataform/google/cloud/dataform_v1beta1/services/dataform/transports/rest.py index d6053a59f80e..a46a32fc09aa 100644 --- a/packages/google-cloud-dataform/google/cloud/dataform_v1beta1/services/dataform/transports/rest.py +++ b/packages/google-cloud-dataform/google/cloud/dataform_v1beta1/services/dataform/transports/rest.py @@ -181,6 +181,14 @@ def pre_delete_folder(self, request, metadata): logging.log(f"Received request: {request}") return request, metadata + def pre_delete_folder_tree(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_delete_folder_tree(self, response): + logging.log(f"Received response: {response}") + return response + def pre_delete_release_config(self, request, metadata): logging.log(f"Received request: {request}") return request, metadata @@ -189,10 +197,26 @@ def pre_delete_repository(self, request, metadata): logging.log(f"Received request: {request}") return request, metadata + def pre_delete_repository_long_running(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_delete_repository_long_running(self, response): + logging.log(f"Received response: {response}") + return response + def pre_delete_team_folder(self, request, metadata): logging.log(f"Received request: {request}") return request, metadata + def pre_delete_team_folder_tree(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_delete_team_folder_tree(self, response): + logging.log(f"Received response: {response}") + return response + def pre_delete_workflow_config(self, request, metadata): logging.log(f"Received request: {request}") return request, metadata @@ -1223,6 +1247,54 @@ def pre_delete_folder( """ return request, metadata + def pre_delete_folder_tree( + self, + request: dataform.DeleteFolderTreeRequest, + metadata: Sequence[Tuple[str, Union[str, bytes]]], + ) -> Tuple[ + dataform.DeleteFolderTreeRequest, Sequence[Tuple[str, Union[str, bytes]]] + ]: + """Pre-rpc interceptor for delete_folder_tree + + Override in a subclass to manipulate the request or metadata + before they are sent to the Dataform server. + """ + return request, metadata + + def post_delete_folder_tree( + self, response: operations_pb2.Operation + ) -> operations_pb2.Operation: + """Post-rpc interceptor for delete_folder_tree + + DEPRECATED. Please use the `post_delete_folder_tree_with_metadata` + interceptor instead. + + Override in a subclass to read or manipulate the response + after it is returned by the Dataform server but before + it is returned to user code. This `post_delete_folder_tree` interceptor runs + before the `post_delete_folder_tree_with_metadata` interceptor. + """ + return response + + def post_delete_folder_tree_with_metadata( + self, + response: operations_pb2.Operation, + metadata: Sequence[Tuple[str, Union[str, bytes]]], + ) -> Tuple[operations_pb2.Operation, Sequence[Tuple[str, Union[str, bytes]]]]: + """Post-rpc interceptor for delete_folder_tree + + Override in a subclass to read or manipulate the response or metadata after it + is returned by the Dataform server but before it is returned to user code. + + We recommend only using this `post_delete_folder_tree_with_metadata` + interceptor in new development instead of the `post_delete_folder_tree` interceptor. + When both interceptors are used, this `post_delete_folder_tree_with_metadata` interceptor runs after the + `post_delete_folder_tree` interceptor. The (possibly modified) response returned by + `post_delete_folder_tree` will be passed to + `post_delete_folder_tree_with_metadata`. + """ + return response, metadata + def pre_delete_release_config( self, request: dataform.DeleteReleaseConfigRequest, @@ -1251,6 +1323,55 @@ def pre_delete_repository( """ return request, metadata + def pre_delete_repository_long_running( + self, + request: dataform.DeleteRepositoryLongRunningRequest, + metadata: Sequence[Tuple[str, Union[str, bytes]]], + ) -> Tuple[ + dataform.DeleteRepositoryLongRunningRequest, + Sequence[Tuple[str, Union[str, bytes]]], + ]: + """Pre-rpc interceptor for delete_repository_long_running + + Override in a subclass to manipulate the request or metadata + before they are sent to the Dataform server. + """ + return request, metadata + + def post_delete_repository_long_running( + self, response: operations_pb2.Operation + ) -> operations_pb2.Operation: + """Post-rpc interceptor for delete_repository_long_running + + DEPRECATED. Please use the `post_delete_repository_long_running_with_metadata` + interceptor instead. + + Override in a subclass to read or manipulate the response + after it is returned by the Dataform server but before + it is returned to user code. This `post_delete_repository_long_running` interceptor runs + before the `post_delete_repository_long_running_with_metadata` interceptor. + """ + return response + + def post_delete_repository_long_running_with_metadata( + self, + response: operations_pb2.Operation, + metadata: Sequence[Tuple[str, Union[str, bytes]]], + ) -> Tuple[operations_pb2.Operation, Sequence[Tuple[str, Union[str, bytes]]]]: + """Post-rpc interceptor for delete_repository_long_running + + Override in a subclass to read or manipulate the response or metadata after it + is returned by the Dataform server but before it is returned to user code. + + We recommend only using this `post_delete_repository_long_running_with_metadata` + interceptor in new development instead of the `post_delete_repository_long_running` interceptor. + When both interceptors are used, this `post_delete_repository_long_running_with_metadata` interceptor runs after the + `post_delete_repository_long_running` interceptor. The (possibly modified) response returned by + `post_delete_repository_long_running` will be passed to + `post_delete_repository_long_running_with_metadata`. + """ + return response, metadata + def pre_delete_team_folder( self, request: dataform.DeleteTeamFolderRequest, @@ -1265,6 +1386,54 @@ def pre_delete_team_folder( """ return request, metadata + def pre_delete_team_folder_tree( + self, + request: dataform.DeleteTeamFolderTreeRequest, + metadata: Sequence[Tuple[str, Union[str, bytes]]], + ) -> Tuple[ + dataform.DeleteTeamFolderTreeRequest, Sequence[Tuple[str, Union[str, bytes]]] + ]: + """Pre-rpc interceptor for delete_team_folder_tree + + Override in a subclass to manipulate the request or metadata + before they are sent to the Dataform server. + """ + return request, metadata + + def post_delete_team_folder_tree( + self, response: operations_pb2.Operation + ) -> operations_pb2.Operation: + """Post-rpc interceptor for delete_team_folder_tree + + DEPRECATED. Please use the `post_delete_team_folder_tree_with_metadata` + interceptor instead. + + Override in a subclass to read or manipulate the response + after it is returned by the Dataform server but before + it is returned to user code. This `post_delete_team_folder_tree` interceptor runs + before the `post_delete_team_folder_tree_with_metadata` interceptor. + """ + return response + + def post_delete_team_folder_tree_with_metadata( + self, + response: operations_pb2.Operation, + metadata: Sequence[Tuple[str, Union[str, bytes]]], + ) -> Tuple[operations_pb2.Operation, Sequence[Tuple[str, Union[str, bytes]]]]: + """Post-rpc interceptor for delete_team_folder_tree + + Override in a subclass to read or manipulate the response or metadata after it + is returned by the Dataform server but before it is returned to user code. + + We recommend only using this `post_delete_team_folder_tree_with_metadata` + interceptor in new development instead of the `post_delete_team_folder_tree` interceptor. + When both interceptors are used, this `post_delete_team_folder_tree_with_metadata` interceptor runs after the + `post_delete_team_folder_tree` interceptor. The (possibly modified) response returned by + `post_delete_team_folder_tree` will be passed to + `post_delete_team_folder_tree_with_metadata`. + """ + return response, metadata + def pre_delete_workflow_config( self, request: dataform.DeleteWorkflowConfigRequest, @@ -5903,24 +6072,431 @@ def __call__( "headers": dict(metadata), } _LOGGER.debug( - f"Sending request for google.cloud.dataform_v1beta1.DataformClient.CreateWorkspace", + f"Sending request for google.cloud.dataform_v1beta1.DataformClient.CreateWorkspace", + extra={ + "serviceName": "google.cloud.dataform.v1beta1.Dataform", + "rpcName": "CreateWorkspace", + "httpRequest": http_request, + "metadata": http_request["headers"], + }, + ) + + # Send the request + response = DataformRestTransport._CreateWorkspace._get_response( + self._host, + metadata, + query_params, + self._session, + timeout, + transcoded_request, + 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 = dataform.Workspace() + pb_resp = dataform.Workspace.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + + resp = self._interceptor.post_create_workspace(resp) + response_metadata = [(k, str(v)) for k, v in response.headers.items()] + resp, _ = self._interceptor.post_create_workspace_with_metadata( + resp, response_metadata + ) + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + logging.DEBUG + ): # pragma: NO COVER + try: + response_payload = dataform.Workspace.to_json(response) + except: + response_payload = None + http_response = { + "payload": response_payload, + "headers": dict(response.headers), + "status": response.status_code, + } + _LOGGER.debug( + "Received response for google.cloud.dataform_v1beta1.DataformClient.create_workspace", + extra={ + "serviceName": "google.cloud.dataform.v1beta1.Dataform", + "rpcName": "CreateWorkspace", + "metadata": http_response["headers"], + "httpResponse": http_response, + }, + ) + return resp + + class _DeleteFolder(_BaseDataformRestTransport._BaseDeleteFolder, DataformRestStub): + def __hash__(self): + return hash("DataformRestTransport.DeleteFolder") + + @staticmethod + def _get_response( + host, + metadata, + query_params, + session, + timeout, + transcoded_request, + body=None, + ): + uri = transcoded_request["uri"] + method = transcoded_request["method"] + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(session, method)( + "{host}{uri}".format(host=host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + ) + return response + + def __call__( + self, + request: dataform.DeleteFolderRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ): + r"""Call the delete folder method over HTTP. + + Args: + request (~.dataform.DeleteFolderRequest): + The request object. ``DeleteFolder`` request message. + 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + """ + + http_options = ( + _BaseDataformRestTransport._BaseDeleteFolder._get_http_options() + ) + + request, metadata = self._interceptor.pre_delete_folder(request, metadata) + transcoded_request = ( + _BaseDataformRestTransport._BaseDeleteFolder._get_transcoded_request( + http_options, request + ) + ) + + # Jsonify the query params + query_params = ( + _BaseDataformRestTransport._BaseDeleteFolder._get_query_params_json( + transcoded_request + ) + ) + + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + logging.DEBUG + ): # pragma: NO COVER + request_url = "{host}{uri}".format( + host=self._host, uri=transcoded_request["uri"] + ) + method = transcoded_request["method"] + try: + request_payload = type(request).to_json(request) + except: + request_payload = None + http_request = { + "payload": request_payload, + "requestMethod": method, + "requestUrl": request_url, + "headers": dict(metadata), + } + _LOGGER.debug( + f"Sending request for google.cloud.dataform_v1beta1.DataformClient.DeleteFolder", + extra={ + "serviceName": "google.cloud.dataform.v1beta1.Dataform", + "rpcName": "DeleteFolder", + "httpRequest": http_request, + "metadata": http_request["headers"], + }, + ) + + # Send the request + response = DataformRestTransport._DeleteFolder._get_response( + self._host, + metadata, + query_params, + self._session, + timeout, + transcoded_request, + ) + + # 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 _DeleteFolderTree( + _BaseDataformRestTransport._BaseDeleteFolderTree, DataformRestStub + ): + def __hash__(self): + return hash("DataformRestTransport.DeleteFolderTree") + + @staticmethod + def _get_response( + host, + metadata, + query_params, + session, + timeout, + transcoded_request, + body=None, + ): + uri = transcoded_request["uri"] + method = transcoded_request["method"] + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(session, method)( + "{host}{uri}".format(host=host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + data=body, + ) + return response + + def __call__( + self, + request: dataform.DeleteFolderTreeRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> operations_pb2.Operation: + r"""Call the delete folder tree method over HTTP. + + Args: + request (~.dataform.DeleteFolderTreeRequest): + The request object. ``DeleteFolderTree`` request message. + 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + ~.operations_pb2.Operation: + This resource represents a + long-running operation that is the + result of a network API call. + + """ + + http_options = ( + _BaseDataformRestTransport._BaseDeleteFolderTree._get_http_options() + ) + + request, metadata = self._interceptor.pre_delete_folder_tree( + request, metadata + ) + transcoded_request = _BaseDataformRestTransport._BaseDeleteFolderTree._get_transcoded_request( + http_options, request + ) + + body = ( + _BaseDataformRestTransport._BaseDeleteFolderTree._get_request_body_json( + transcoded_request + ) + ) + + # Jsonify the query params + query_params = ( + _BaseDataformRestTransport._BaseDeleteFolderTree._get_query_params_json( + transcoded_request + ) + ) + + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + logging.DEBUG + ): # pragma: NO COVER + request_url = "{host}{uri}".format( + host=self._host, uri=transcoded_request["uri"] + ) + method = transcoded_request["method"] + try: + request_payload = type(request).to_json(request) + except: + request_payload = None + http_request = { + "payload": request_payload, + "requestMethod": method, + "requestUrl": request_url, + "headers": dict(metadata), + } + _LOGGER.debug( + f"Sending request for google.cloud.dataform_v1beta1.DataformClient.DeleteFolderTree", + extra={ + "serviceName": "google.cloud.dataform.v1beta1.Dataform", + "rpcName": "DeleteFolderTree", + "httpRequest": http_request, + "metadata": http_request["headers"], + }, + ) + + # Send the request + response = DataformRestTransport._DeleteFolderTree._get_response( + self._host, + metadata, + query_params, + self._session, + timeout, + transcoded_request, + 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_delete_folder_tree(resp) + response_metadata = [(k, str(v)) for k, v in response.headers.items()] + resp, _ = self._interceptor.post_delete_folder_tree_with_metadata( + resp, response_metadata + ) + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + logging.DEBUG + ): # pragma: NO COVER + try: + response_payload = json_format.MessageToJson(resp) + except: + response_payload = None + http_response = { + "payload": response_payload, + "headers": dict(response.headers), + "status": response.status_code, + } + _LOGGER.debug( + "Received response for google.cloud.dataform_v1beta1.DataformClient.delete_folder_tree", + extra={ + "serviceName": "google.cloud.dataform.v1beta1.Dataform", + "rpcName": "DeleteFolderTree", + "metadata": http_response["headers"], + "httpResponse": http_response, + }, + ) + return resp + + class _DeleteReleaseConfig( + _BaseDataformRestTransport._BaseDeleteReleaseConfig, DataformRestStub + ): + def __hash__(self): + return hash("DataformRestTransport.DeleteReleaseConfig") + + @staticmethod + def _get_response( + host, + metadata, + query_params, + session, + timeout, + transcoded_request, + body=None, + ): + uri = transcoded_request["uri"] + method = transcoded_request["method"] + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(session, method)( + "{host}{uri}".format(host=host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + ) + return response + + def __call__( + self, + request: dataform.DeleteReleaseConfigRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ): + r"""Call the delete release config method over HTTP. + + Args: + request (~.dataform.DeleteReleaseConfigRequest): + The request object. ``DeleteReleaseConfig`` request message. + 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + """ + + http_options = ( + _BaseDataformRestTransport._BaseDeleteReleaseConfig._get_http_options() + ) + + request, metadata = self._interceptor.pre_delete_release_config( + request, metadata + ) + transcoded_request = _BaseDataformRestTransport._BaseDeleteReleaseConfig._get_transcoded_request( + http_options, request + ) + + # Jsonify the query params + query_params = _BaseDataformRestTransport._BaseDeleteReleaseConfig._get_query_params_json( + transcoded_request + ) + + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + logging.DEBUG + ): # pragma: NO COVER + request_url = "{host}{uri}".format( + host=self._host, uri=transcoded_request["uri"] + ) + method = transcoded_request["method"] + try: + request_payload = type(request).to_json(request) + except: + request_payload = None + http_request = { + "payload": request_payload, + "requestMethod": method, + "requestUrl": request_url, + "headers": dict(metadata), + } + _LOGGER.debug( + f"Sending request for google.cloud.dataform_v1beta1.DataformClient.DeleteReleaseConfig", extra={ "serviceName": "google.cloud.dataform.v1beta1.Dataform", - "rpcName": "CreateWorkspace", + "rpcName": "DeleteReleaseConfig", "httpRequest": http_request, "metadata": http_request["headers"], }, ) # Send the request - response = DataformRestTransport._CreateWorkspace._get_response( + response = DataformRestTransport._DeleteReleaseConfig._get_response( self._host, metadata, query_params, self._session, timeout, transcoded_request, - body, ) # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception @@ -5928,43 +6504,11 @@ def __call__( if response.status_code >= 400: raise core_exceptions.from_http_response(response) - # Return the response - resp = dataform.Workspace() - pb_resp = dataform.Workspace.pb(resp) - - json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) - - resp = self._interceptor.post_create_workspace(resp) - response_metadata = [(k, str(v)) for k, v in response.headers.items()] - resp, _ = self._interceptor.post_create_workspace_with_metadata( - resp, response_metadata - ) - if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( - logging.DEBUG - ): # pragma: NO COVER - try: - response_payload = dataform.Workspace.to_json(response) - except: - response_payload = None - http_response = { - "payload": response_payload, - "headers": dict(response.headers), - "status": response.status_code, - } - _LOGGER.debug( - "Received response for google.cloud.dataform_v1beta1.DataformClient.create_workspace", - extra={ - "serviceName": "google.cloud.dataform.v1beta1.Dataform", - "rpcName": "CreateWorkspace", - "metadata": http_response["headers"], - "httpResponse": http_response, - }, - ) - return resp - - class _DeleteFolder(_BaseDataformRestTransport._BaseDeleteFolder, DataformRestStub): + class _DeleteRepository( + _BaseDataformRestTransport._BaseDeleteRepository, DataformRestStub + ): def __hash__(self): - return hash("DataformRestTransport.DeleteFolder") + return hash("DataformRestTransport.DeleteRepository") @staticmethod def _get_response( @@ -5990,17 +6534,17 @@ def _get_response( def __call__( self, - request: dataform.DeleteFolderRequest, + request: dataform.DeleteRepositoryRequest, *, retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: Optional[float] = None, metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), ): - r"""Call the delete folder method over HTTP. + r"""Call the delete repository method over HTTP. Args: - request (~.dataform.DeleteFolderRequest): - The request object. ``DeleteFolder`` request message. + request (~.dataform.DeleteRepositoryRequest): + The request object. ``DeleteRepository`` request message. retry (google.api_core.retry.Retry): Designation of what errors, if any, should be retried. timeout (float): The timeout for this request. @@ -6011,19 +6555,19 @@ def __call__( """ http_options = ( - _BaseDataformRestTransport._BaseDeleteFolder._get_http_options() + _BaseDataformRestTransport._BaseDeleteRepository._get_http_options() ) - request, metadata = self._interceptor.pre_delete_folder(request, metadata) - transcoded_request = ( - _BaseDataformRestTransport._BaseDeleteFolder._get_transcoded_request( - http_options, request - ) + request, metadata = self._interceptor.pre_delete_repository( + request, metadata + ) + transcoded_request = _BaseDataformRestTransport._BaseDeleteRepository._get_transcoded_request( + http_options, request ) # Jsonify the query params query_params = ( - _BaseDataformRestTransport._BaseDeleteFolder._get_query_params_json( + _BaseDataformRestTransport._BaseDeleteRepository._get_query_params_json( transcoded_request ) ) @@ -6046,17 +6590,17 @@ def __call__( "headers": dict(metadata), } _LOGGER.debug( - f"Sending request for google.cloud.dataform_v1beta1.DataformClient.DeleteFolder", + f"Sending request for google.cloud.dataform_v1beta1.DataformClient.DeleteRepository", extra={ "serviceName": "google.cloud.dataform.v1beta1.Dataform", - "rpcName": "DeleteFolder", + "rpcName": "DeleteRepository", "httpRequest": http_request, "metadata": http_request["headers"], }, ) # Send the request - response = DataformRestTransport._DeleteFolder._get_response( + response = DataformRestTransport._DeleteRepository._get_response( self._host, metadata, query_params, @@ -6070,11 +6614,11 @@ def __call__( if response.status_code >= 400: raise core_exceptions.from_http_response(response) - class _DeleteReleaseConfig( - _BaseDataformRestTransport._BaseDeleteReleaseConfig, DataformRestStub + class _DeleteRepositoryLongRunning( + _BaseDataformRestTransport._BaseDeleteRepositoryLongRunning, DataformRestStub ): def __hash__(self): - return hash("DataformRestTransport.DeleteReleaseConfig") + return hash("DataformRestTransport.DeleteRepositoryLongRunning") @staticmethod def _get_response( @@ -6095,44 +6639,55 @@ def _get_response( timeout=timeout, headers=headers, params=rest_helpers.flatten_query_params(query_params, strict=True), + data=body, ) return response def __call__( self, - request: dataform.DeleteReleaseConfigRequest, + request: dataform.DeleteRepositoryLongRunningRequest, *, retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: Optional[float] = None, metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), - ): - r"""Call the delete release config method over HTTP. + ) -> operations_pb2.Operation: + r"""Call the delete repository long + running method over HTTP. + + Args: + request (~.dataform.DeleteRepositoryLongRunningRequest): + The request object. ``DeleteRepositoryLongRunning`` request message. + 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + ~.operations_pb2.Operation: + This resource represents a + long-running operation that is the + result of a network API call. - Args: - request (~.dataform.DeleteReleaseConfigRequest): - The request object. ``DeleteReleaseConfig`` request message. - 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, Union[str, bytes]]]): Key/value pairs which should be - sent along with the request as metadata. Normally, each value must be of type `str`, - but for metadata keys ending with the suffix `-bin`, the corresponding values must - be of type `bytes`. """ - http_options = ( - _BaseDataformRestTransport._BaseDeleteReleaseConfig._get_http_options() - ) + http_options = _BaseDataformRestTransport._BaseDeleteRepositoryLongRunning._get_http_options() - request, metadata = self._interceptor.pre_delete_release_config( + request, metadata = self._interceptor.pre_delete_repository_long_running( request, metadata ) - transcoded_request = _BaseDataformRestTransport._BaseDeleteReleaseConfig._get_transcoded_request( + transcoded_request = _BaseDataformRestTransport._BaseDeleteRepositoryLongRunning._get_transcoded_request( http_options, request ) + body = _BaseDataformRestTransport._BaseDeleteRepositoryLongRunning._get_request_body_json( + transcoded_request + ) + # Jsonify the query params - query_params = _BaseDataformRestTransport._BaseDeleteReleaseConfig._get_query_params_json( + query_params = _BaseDataformRestTransport._BaseDeleteRepositoryLongRunning._get_query_params_json( transcoded_request ) @@ -6154,23 +6709,24 @@ def __call__( "headers": dict(metadata), } _LOGGER.debug( - f"Sending request for google.cloud.dataform_v1beta1.DataformClient.DeleteReleaseConfig", + f"Sending request for google.cloud.dataform_v1beta1.DataformClient.DeleteRepositoryLongRunning", extra={ "serviceName": "google.cloud.dataform.v1beta1.Dataform", - "rpcName": "DeleteReleaseConfig", + "rpcName": "DeleteRepositoryLongRunning", "httpRequest": http_request, "metadata": http_request["headers"], }, ) # Send the request - response = DataformRestTransport._DeleteReleaseConfig._get_response( + response = DataformRestTransport._DeleteRepositoryLongRunning._get_response( self._host, metadata, query_params, self._session, timeout, transcoded_request, + body, ) # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception @@ -6178,11 +6734,45 @@ def __call__( if response.status_code >= 400: raise core_exceptions.from_http_response(response) - class _DeleteRepository( - _BaseDataformRestTransport._BaseDeleteRepository, DataformRestStub + # Return the response + resp = operations_pb2.Operation() + json_format.Parse(response.content, resp, ignore_unknown_fields=True) + + resp = self._interceptor.post_delete_repository_long_running(resp) + response_metadata = [(k, str(v)) for k, v in response.headers.items()] + resp, _ = ( + self._interceptor.post_delete_repository_long_running_with_metadata( + resp, response_metadata + ) + ) + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + logging.DEBUG + ): # pragma: NO COVER + try: + response_payload = json_format.MessageToJson(resp) + except: + response_payload = None + http_response = { + "payload": response_payload, + "headers": dict(response.headers), + "status": response.status_code, + } + _LOGGER.debug( + "Received response for google.cloud.dataform_v1beta1.DataformClient.delete_repository_long_running", + extra={ + "serviceName": "google.cloud.dataform.v1beta1.Dataform", + "rpcName": "DeleteRepositoryLongRunning", + "metadata": http_response["headers"], + "httpResponse": http_response, + }, + ) + return resp + + class _DeleteTeamFolder( + _BaseDataformRestTransport._BaseDeleteTeamFolder, DataformRestStub ): def __hash__(self): - return hash("DataformRestTransport.DeleteRepository") + return hash("DataformRestTransport.DeleteTeamFolder") @staticmethod def _get_response( @@ -6208,17 +6798,17 @@ def _get_response( def __call__( self, - request: dataform.DeleteRepositoryRequest, + request: dataform.DeleteTeamFolderRequest, *, retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: Optional[float] = None, metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), ): - r"""Call the delete repository method over HTTP. + r"""Call the delete team folder method over HTTP. Args: - request (~.dataform.DeleteRepositoryRequest): - The request object. ``DeleteRepository`` request message. + request (~.dataform.DeleteTeamFolderRequest): + The request object. ``DeleteTeamFolder`` request message. retry (google.api_core.retry.Retry): Designation of what errors, if any, should be retried. timeout (float): The timeout for this request. @@ -6229,19 +6819,19 @@ def __call__( """ http_options = ( - _BaseDataformRestTransport._BaseDeleteRepository._get_http_options() + _BaseDataformRestTransport._BaseDeleteTeamFolder._get_http_options() ) - request, metadata = self._interceptor.pre_delete_repository( + request, metadata = self._interceptor.pre_delete_team_folder( request, metadata ) - transcoded_request = _BaseDataformRestTransport._BaseDeleteRepository._get_transcoded_request( + transcoded_request = _BaseDataformRestTransport._BaseDeleteTeamFolder._get_transcoded_request( http_options, request ) # Jsonify the query params query_params = ( - _BaseDataformRestTransport._BaseDeleteRepository._get_query_params_json( + _BaseDataformRestTransport._BaseDeleteTeamFolder._get_query_params_json( transcoded_request ) ) @@ -6264,17 +6854,17 @@ def __call__( "headers": dict(metadata), } _LOGGER.debug( - f"Sending request for google.cloud.dataform_v1beta1.DataformClient.DeleteRepository", + f"Sending request for google.cloud.dataform_v1beta1.DataformClient.DeleteTeamFolder", extra={ "serviceName": "google.cloud.dataform.v1beta1.Dataform", - "rpcName": "DeleteRepository", + "rpcName": "DeleteTeamFolder", "httpRequest": http_request, "metadata": http_request["headers"], }, ) # Send the request - response = DataformRestTransport._DeleteRepository._get_response( + response = DataformRestTransport._DeleteTeamFolder._get_response( self._host, metadata, query_params, @@ -6288,11 +6878,11 @@ def __call__( if response.status_code >= 400: raise core_exceptions.from_http_response(response) - class _DeleteTeamFolder( - _BaseDataformRestTransport._BaseDeleteTeamFolder, DataformRestStub + class _DeleteTeamFolderTree( + _BaseDataformRestTransport._BaseDeleteTeamFolderTree, DataformRestStub ): def __hash__(self): - return hash("DataformRestTransport.DeleteTeamFolder") + return hash("DataformRestTransport.DeleteTeamFolderTree") @staticmethod def _get_response( @@ -6313,22 +6903,23 @@ def _get_response( timeout=timeout, headers=headers, params=rest_helpers.flatten_query_params(query_params, strict=True), + data=body, ) return response def __call__( self, - request: dataform.DeleteTeamFolderRequest, + request: dataform.DeleteTeamFolderTreeRequest, *, retry: OptionalRetry = gapic_v1.method.DEFAULT, timeout: Optional[float] = None, metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), - ): - r"""Call the delete team folder method over HTTP. + ) -> operations_pb2.Operation: + r"""Call the delete team folder tree method over HTTP. Args: - request (~.dataform.DeleteTeamFolderRequest): - The request object. ``DeleteTeamFolder`` request message. + request (~.dataform.DeleteTeamFolderTreeRequest): + The request object. ``DeleteTeamFolderTree`` request message. retry (google.api_core.retry.Retry): Designation of what errors, if any, should be retried. timeout (float): The timeout for this request. @@ -6336,24 +6927,33 @@ def __call__( sent along with the request as metadata. Normally, each value must be of type `str`, but for metadata keys ending with the suffix `-bin`, the corresponding values must be of type `bytes`. + + Returns: + ~.operations_pb2.Operation: + This resource represents a + long-running operation that is the + result of a network API call. + """ http_options = ( - _BaseDataformRestTransport._BaseDeleteTeamFolder._get_http_options() + _BaseDataformRestTransport._BaseDeleteTeamFolderTree._get_http_options() ) - request, metadata = self._interceptor.pre_delete_team_folder( + request, metadata = self._interceptor.pre_delete_team_folder_tree( request, metadata ) - transcoded_request = _BaseDataformRestTransport._BaseDeleteTeamFolder._get_transcoded_request( + transcoded_request = _BaseDataformRestTransport._BaseDeleteTeamFolderTree._get_transcoded_request( http_options, request ) + body = _BaseDataformRestTransport._BaseDeleteTeamFolderTree._get_request_body_json( + transcoded_request + ) + # Jsonify the query params - query_params = ( - _BaseDataformRestTransport._BaseDeleteTeamFolder._get_query_params_json( - transcoded_request - ) + query_params = _BaseDataformRestTransport._BaseDeleteTeamFolderTree._get_query_params_json( + transcoded_request ) if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( @@ -6374,23 +6974,24 @@ def __call__( "headers": dict(metadata), } _LOGGER.debug( - f"Sending request for google.cloud.dataform_v1beta1.DataformClient.DeleteTeamFolder", + f"Sending request for google.cloud.dataform_v1beta1.DataformClient.DeleteTeamFolderTree", extra={ "serviceName": "google.cloud.dataform.v1beta1.Dataform", - "rpcName": "DeleteTeamFolder", + "rpcName": "DeleteTeamFolderTree", "httpRequest": http_request, "metadata": http_request["headers"], }, ) # Send the request - response = DataformRestTransport._DeleteTeamFolder._get_response( + response = DataformRestTransport._DeleteTeamFolderTree._get_response( self._host, metadata, query_params, self._session, timeout, transcoded_request, + body, ) # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception @@ -6398,6 +6999,38 @@ def __call__( 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_delete_team_folder_tree(resp) + response_metadata = [(k, str(v)) for k, v in response.headers.items()] + resp, _ = self._interceptor.post_delete_team_folder_tree_with_metadata( + resp, response_metadata + ) + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + logging.DEBUG + ): # pragma: NO COVER + try: + response_payload = json_format.MessageToJson(resp) + except: + response_payload = None + http_response = { + "payload": response_payload, + "headers": dict(response.headers), + "status": response.status_code, + } + _LOGGER.debug( + "Received response for google.cloud.dataform_v1beta1.DataformClient.delete_team_folder_tree", + extra={ + "serviceName": "google.cloud.dataform.v1beta1.Dataform", + "rpcName": "DeleteTeamFolderTree", + "metadata": http_response["headers"], + "httpResponse": http_response, + }, + ) + return resp + class _DeleteWorkflowConfig( _BaseDataformRestTransport._BaseDeleteWorkflowConfig, DataformRestStub ): @@ -14841,6 +15474,14 @@ def delete_folder( # In C++ this would require a dynamic_cast return self._DeleteFolder(self._session, self._host, self._interceptor) # type: ignore + @property + def delete_folder_tree( + self, + ) -> Callable[[dataform.DeleteFolderTreeRequest], 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._DeleteFolderTree(self._session, self._host, self._interceptor) # type: ignore + @property def delete_release_config( self, @@ -14857,6 +15498,18 @@ def delete_repository( # In C++ this would require a dynamic_cast return self._DeleteRepository(self._session, self._host, self._interceptor) # type: ignore + @property + def delete_repository_long_running( + self, + ) -> Callable[ + [dataform.DeleteRepositoryLongRunningRequest], 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._DeleteRepositoryLongRunning( + self._session, self._host, self._interceptor + ) # type: ignore + @property def delete_team_folder( self, @@ -14865,6 +15518,14 @@ def delete_team_folder( # In C++ this would require a dynamic_cast return self._DeleteTeamFolder(self._session, self._host, self._interceptor) # type: ignore + @property + def delete_team_folder_tree( + self, + ) -> Callable[[dataform.DeleteTeamFolderTreeRequest], 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._DeleteTeamFolderTree(self._session, self._host, self._interceptor) # type: ignore + @property def delete_workflow_config( self, diff --git a/packages/google-cloud-dataform/google/cloud/dataform_v1beta1/services/dataform/transports/rest_base.py b/packages/google-cloud-dataform/google/cloud/dataform_v1beta1/services/dataform/transports/rest_base.py index 9687f003a08d..7cd3c2ac7513 100644 --- a/packages/google-cloud-dataform/google/cloud/dataform_v1beta1/services/dataform/transports/rest_base.py +++ b/packages/google-cloud-dataform/google/cloud/dataform_v1beta1/services/dataform/transports/rest_base.py @@ -825,6 +825,63 @@ def _get_query_params_json(transcoded_request): query_params["$alt"] = "json;enum-encoding=int" return query_params + class _BaseDeleteFolderTree: + def __hash__(self): # pragma: NO COVER + return NotImplementedError("__hash__ must be implemented.") + + __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 + } + + @staticmethod + def _get_http_options(): + http_options: List[Dict[str, str]] = [ + { + "method": "post", + "uri": "/v1beta1/{name=projects/*/locations/*/folders/*}:deleteTree", + "body": "*", + }, + ] + return http_options + + @staticmethod + def _get_transcoded_request(http_options, request): + pb_request = dataform.DeleteFolderTreeRequest.pb(request) + transcoded_request = path_template.transcode(http_options, pb_request) + return transcoded_request + + @staticmethod + def _get_request_body_json(transcoded_request): + # Jsonify the request body + + body = json_format.MessageToJson( + transcoded_request["body"], use_integers_for_enums=True + ) + return body + + @staticmethod + def _get_query_params_json(transcoded_request): + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + use_integers_for_enums=True, + ) + ) + query_params.update( + _BaseDataformRestTransport._BaseDeleteFolderTree._get_unset_required_fields( + query_params + ) + ) + + query_params["$alt"] = "json;enum-encoding=int" + return query_params + class _BaseDeleteReleaseConfig: def __hash__(self): # pragma: NO COVER return NotImplementedError("__hash__ must be implemented.") @@ -919,6 +976,63 @@ def _get_query_params_json(transcoded_request): query_params["$alt"] = "json;enum-encoding=int" return query_params + class _BaseDeleteRepositoryLongRunning: + def __hash__(self): # pragma: NO COVER + return NotImplementedError("__hash__ must be implemented.") + + __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 + } + + @staticmethod + def _get_http_options(): + http_options: List[Dict[str, str]] = [ + { + "method": "post", + "uri": "/v1beta1/{name=projects/*/locations/*/repositories/*}:deleteLongRunning", + "body": "*", + }, + ] + return http_options + + @staticmethod + def _get_transcoded_request(http_options, request): + pb_request = dataform.DeleteRepositoryLongRunningRequest.pb(request) + transcoded_request = path_template.transcode(http_options, pb_request) + return transcoded_request + + @staticmethod + def _get_request_body_json(transcoded_request): + # Jsonify the request body + + body = json_format.MessageToJson( + transcoded_request["body"], use_integers_for_enums=True + ) + return body + + @staticmethod + def _get_query_params_json(transcoded_request): + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + use_integers_for_enums=True, + ) + ) + query_params.update( + _BaseDataformRestTransport._BaseDeleteRepositoryLongRunning._get_unset_required_fields( + query_params + ) + ) + + query_params["$alt"] = "json;enum-encoding=int" + return query_params + class _BaseDeleteTeamFolder: def __hash__(self): # pragma: NO COVER return NotImplementedError("__hash__ must be implemented.") @@ -966,6 +1080,63 @@ def _get_query_params_json(transcoded_request): query_params["$alt"] = "json;enum-encoding=int" return query_params + class _BaseDeleteTeamFolderTree: + def __hash__(self): # pragma: NO COVER + return NotImplementedError("__hash__ must be implemented.") + + __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 + } + + @staticmethod + def _get_http_options(): + http_options: List[Dict[str, str]] = [ + { + "method": "post", + "uri": "/v1beta1/{name=projects/*/locations/*/teamFolders/*}:deleteTree", + "body": "*", + }, + ] + return http_options + + @staticmethod + def _get_transcoded_request(http_options, request): + pb_request = dataform.DeleteTeamFolderTreeRequest.pb(request) + transcoded_request = path_template.transcode(http_options, pb_request) + return transcoded_request + + @staticmethod + def _get_request_body_json(transcoded_request): + # Jsonify the request body + + body = json_format.MessageToJson( + transcoded_request["body"], use_integers_for_enums=True + ) + return body + + @staticmethod + def _get_query_params_json(transcoded_request): + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + use_integers_for_enums=True, + ) + ) + query_params.update( + _BaseDataformRestTransport._BaseDeleteTeamFolderTree._get_unset_required_fields( + query_params + ) + ) + + query_params["$alt"] = "json;enum-encoding=int" + return query_params + class _BaseDeleteWorkflowConfig: def __hash__(self): # pragma: NO COVER return NotImplementedError("__hash__ must be implemented.") diff --git a/packages/google-cloud-dataform/google/cloud/dataform_v1beta1/types/__init__.py b/packages/google-cloud-dataform/google/cloud/dataform_v1beta1/types/__init__.py index b77bf48171cc..033c4e8d2b46 100644 --- a/packages/google-cloud-dataform/google/cloud/dataform_v1beta1/types/__init__.py +++ b/packages/google-cloud-dataform/google/cloud/dataform_v1beta1/types/__init__.py @@ -39,12 +39,19 @@ CreateWorkspaceRequest, DataEncryptionState, DeleteFolderRequest, + DeleteFolderTreeMetadata, + DeleteFolderTreeRequest, DeleteReleaseConfigRequest, + DeleteRepositoryLongRunningMetadata, + DeleteRepositoryLongRunningRequest, + DeleteRepositoryLongRunningResponse, DeleteRepositoryRequest, DeleteTeamFolderRequest, + DeleteTeamFolderTreeRequest, DeleteWorkflowConfigRequest, DeleteWorkflowInvocationRequest, DeleteWorkspaceRequest, + DirectoryContentsView, DirectoryEntry, DirectorySearchResult, FetchFileDiffRequest, @@ -58,6 +65,7 @@ FetchRepositoryHistoryRequest, FetchRepositoryHistoryResponse, FileSearchResult, + FilesystemEntryMetadata, Folder, GetCompilationResultRequest, GetConfigRequest, @@ -173,9 +181,15 @@ "CreateWorkspaceRequest", "DataEncryptionState", "DeleteFolderRequest", + "DeleteFolderTreeMetadata", + "DeleteFolderTreeRequest", "DeleteReleaseConfigRequest", + "DeleteRepositoryLongRunningMetadata", + "DeleteRepositoryLongRunningRequest", + "DeleteRepositoryLongRunningResponse", "DeleteRepositoryRequest", "DeleteTeamFolderRequest", + "DeleteTeamFolderTreeRequest", "DeleteWorkflowConfigRequest", "DeleteWorkflowInvocationRequest", "DeleteWorkspaceRequest", @@ -192,6 +206,7 @@ "FetchRepositoryHistoryRequest", "FetchRepositoryHistoryResponse", "FileSearchResult", + "FilesystemEntryMetadata", "Folder", "GetCompilationResultRequest", "GetConfigRequest", @@ -279,4 +294,5 @@ "Workspace", "WriteFileRequest", "WriteFileResponse", + "DirectoryContentsView", ) diff --git a/packages/google-cloud-dataform/google/cloud/dataform_v1beta1/types/dataform.py b/packages/google-cloud-dataform/google/cloud/dataform_v1beta1/types/dataform.py index 9b017c47f7cc..3d80c9fac09a 100644 --- a/packages/google-cloud-dataform/google/cloud/dataform_v1beta1/types/dataform.py +++ b/packages/google-cloud-dataform/google/cloud/dataform_v1beta1/types/dataform.py @@ -26,6 +26,7 @@ __protobuf__ = proto.module( package="google.cloud.dataform.v1beta1", manifest={ + "DirectoryContentsView", "DataEncryptionState", "Repository", "PrivateResourceMetadata", @@ -36,6 +37,8 @@ "CreateRepositoryRequest", "UpdateRepositoryRequest", "DeleteRepositoryRequest", + "DeleteRepositoryLongRunningResponse", + "DeleteRepositoryLongRunningRequest", "CommitRepositoryChangesRequest", "CommitRepositoryChangesResponse", "ReadRepositoryFileRequest", @@ -74,6 +77,7 @@ "QueryDirectoryContentsRequest", "QueryDirectoryContentsResponse", "DirectoryEntry", + "FilesystemEntryMetadata", "SearchFilesRequest", "SearchFilesResponse", "SearchResult", @@ -142,6 +146,9 @@ "GetFolderRequest", "UpdateFolderRequest", "DeleteFolderRequest", + "DeleteFolderTreeRequest", + "DeleteTeamFolderTreeRequest", + "DeleteFolderTreeMetadata", "QueryFolderContentsRequest", "QueryFolderContentsResponse", "QueryUserRootContentsRequest", @@ -157,10 +164,33 @@ "SearchTeamFoldersResponse", "MoveFolderMetadata", "MoveRepositoryMetadata", + "DeleteRepositoryLongRunningMetadata", }, ) +class DirectoryContentsView(proto.Enum): + r"""Represents the level of detail to return for directory + contents. + + Values: + DIRECTORY_CONTENTS_VIEW_UNSPECIFIED (0): + The default unset value. Defaults to + DIRECTORY_CONTENTS_VIEW_BASIC. + DIRECTORY_CONTENTS_VIEW_BASIC (1): + Includes only the file or directory name. + This is the default behavior. + DIRECTORY_CONTENTS_VIEW_METADATA (2): + Includes all metadata for each file or + directory. Currently not supported by + CMEK-protected workspaces. + """ + + DIRECTORY_CONTENTS_VIEW_UNSPECIFIED = 0 + DIRECTORY_CONTENTS_VIEW_BASIC = 1 + DIRECTORY_CONTENTS_VIEW_METADATA = 2 + + class DataEncryptionState(proto.Message): r"""Describes encryption state of a resource. @@ -259,12 +289,18 @@ class Repository(proto.Message): class GitRemoteSettings(proto.Message): r"""Controls Git remote configuration for a repository. + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: url (str): Required. The Git remote's URL. default_branch (str): - Required. The Git remote's default branch - name. + Optional. The Git remote's default branch name. If not set, + ``main`` will be used. + effective_default_branch (str): + Output only. The Git remote's effective default branch name. + This is the default branch name of the Git remote if it is + set, otherwise it is ``main``. authentication_token_secret_version (str): Optional. The name of the Secret Manager secret version to use as an authentication token for Git operations. Must be @@ -272,6 +308,12 @@ class GitRemoteSettings(proto.Message): ssh_authentication_config (google.cloud.dataform_v1beta1.types.Repository.GitRemoteSettings.SshAuthenticationConfig): Optional. Authentication fields for remote uris using SSH protocol. + git_repository_link (str): + Optional. Resource name for the ``GitRepositoryLink`` used + for machine credentials. Must be in the format + ``projects/*/locations/*/connections/*/gitRepositoryLinks/*`` + + This field is a member of `oneof`_ ``_git_repository_link``. token_status (google.cloud.dataform_v1beta1.types.Repository.GitRemoteSettings.TokenStatus): Output only. Deprecated: The field does not contain any token status information. Instead @@ -332,6 +374,10 @@ class SshAuthenticationConfig(proto.Message): proto.STRING, number=2, ) + effective_default_branch: str = proto.Field( + proto.STRING, + number=9, + ) authentication_token_secret_version: str = proto.Field( proto.STRING, number=3, @@ -341,6 +387,11 @@ class SshAuthenticationConfig(proto.Message): number=5, message="Repository.GitRemoteSettings.SshAuthenticationConfig", ) + git_repository_link: str = proto.Field( + proto.STRING, + number=7, + optional=True, + ) token_status: "Repository.GitRemoteSettings.TokenStatus" = proto.Field( proto.ENUM, number=4, @@ -674,6 +725,37 @@ class DeleteRepositoryRequest(proto.Message): ) +class DeleteRepositoryLongRunningResponse(proto.Message): + r"""``DeleteRepositoryLongRunning`` response message.""" + + +class DeleteRepositoryLongRunningRequest(proto.Message): + r"""``DeleteRepositoryLongRunning`` request message. + + Attributes: + name (str): + Required. The repository's name. + force (bool): + Optional. If set to true, child resources of this repository + (compilation results and workflow invocations) will also be + deleted. Otherwise, the request will only succeed if the + repository has no child resources. + + **Note:** *This flag doesn't support deletion of workspaces, + release configs or workflow configs. If any of such + resources exists in the repository, the request will fail.* + """ + + name: str = proto.Field( + proto.STRING, + number=1, + ) + force: bool = proto.Field( + proto.BOOL, + number=2, + ) + + class CommitRepositoryChangesRequest(proto.Message): r"""``CommitRepositoryChanges`` request message. @@ -1064,12 +1146,16 @@ class TokenStatus(proto.Enum): VALID (3): The token was used successfully to authenticate against the Git remote. + PERMISSION_DENIED (4): + The token is not accessible due to permission + issues. """ TOKEN_STATUS_UNSPECIFIED = 0 NOT_FOUND = 1 INVALID = 2 VALID = 3 + PERMISSION_DENIED = 4 token_status: TokenStatus = proto.Field( proto.ENUM, @@ -1651,6 +1737,12 @@ class QueryDirectoryContentsRequest(proto.Message): ``QueryDirectoryContents``, with the exception of ``page_size``, must match the call that provided the page token. + view (google.cloud.dataform_v1beta1.types.DirectoryContentsView): + Optional. Specifies the metadata to return for each + directory entry. If unspecified, the default is + ``DIRECTORY_CONTENTS_VIEW_BASIC``. Currently the + ``DIRECTORY_CONTENTS_VIEW_METADATA`` view is not supported + by CMEK-protected workspaces. """ workspace: str = proto.Field( @@ -1669,6 +1761,11 @@ class QueryDirectoryContentsRequest(proto.Message): proto.STRING, number=4, ) + view: "DirectoryContentsView" = proto.Field( + proto.ENUM, + number=5, + enum="DirectoryContentsView", + ) class QueryDirectoryContentsResponse(proto.Message): @@ -1710,13 +1807,19 @@ class DirectoryEntry(proto.Message): Attributes: file (str): - A file in the directory. + A file in the directory. The path is returned + including the full folder structure from the + root. This field is a member of `oneof`_ ``entry``. directory (str): - A child directory in the directory. + A child directory in the directory. The path + is returned including the full folder structure + from the root. This field is a member of `oneof`_ ``entry``. + metadata (google.cloud.dataform_v1beta1.types.FilesystemEntryMetadata): + Entry with metadata. """ file: str = proto.Field( @@ -1729,6 +1832,34 @@ class DirectoryEntry(proto.Message): number=2, oneof="entry", ) + metadata: "FilesystemEntryMetadata" = proto.Field( + proto.MESSAGE, + number=3, + message="FilesystemEntryMetadata", + ) + + +class FilesystemEntryMetadata(proto.Message): + r"""Represents metadata for a single entry in a filesystem. + + Attributes: + size_bytes (int): + Output only. Provides the size of the entry + in bytes. For directories, this will be 0. + update_time (google.protobuf.timestamp_pb2.Timestamp): + Output only. Represents the time of the last + modification of the entry. + """ + + size_bytes: int = proto.Field( + proto.INT64, + number=1, + ) + update_time: timestamp_pb2.Timestamp = proto.Field( + proto.MESSAGE, + number=2, + message=timestamp_pb2.Timestamp, + ) class SearchFilesRequest(proto.Message): @@ -4451,11 +4582,11 @@ class NotebookAction(proto.Message): Output only. The code contents of a Notebook to be run. job_id (str): - Output only. The ID of the Vertex job that - executed the notebook in contents and also the - ID used for the outputs created in Google Cloud - Storage buckets. Only set once the job has - started to run. + Output only. The ID of the Gemini Enterprise + Agent Platform job that executed the notebook in + contents and also the ID used for the outputs + created in Google Cloud Storage buckets. Only + set once the job has started to run. """ contents: str = proto.Field( @@ -4849,9 +4980,8 @@ class Folder(proto.Message): name. This should take the format: projects/{project}/locations/{location}/folders/{folder}, projects/{project}/locations/{location}/teamFolders/{teamFolder}, - or just projects/{project}/locations/{location} - if this is a root Folder. This field can only be - updated through MoveFolder. + or just "" if this is a root Folder. This field + can only be updated through MoveFolder. team_folder_name (str): Output only. The resource name of the TeamFolder that this Folder is associated with. @@ -4928,9 +5058,11 @@ class CreateFolderRequest(proto.Message): folder (google.cloud.dataform_v1beta1.types.Folder): Required. The Folder to create. folder_id (str): - The ID to use for the Folder, which will - become the final component of the Folder's - resource name. + Deprecated: This field is not used. The + resource name is generated automatically. + The ID to use for the Folder, which will become + the final component of the Folder's resource + name. """ parent: str = proto.Field( @@ -5032,13 +5164,140 @@ class DeleteFolderRequest(proto.Message): ) +class DeleteFolderTreeRequest(proto.Message): + r"""``DeleteFolderTree`` request message. + + Attributes: + name (str): + Required. The Folder's name. + Format: + projects/{project}/locations/{location}/folders/{folder} + force (bool): + Optional. If ``false`` (default): The operation will fail if + any Repository within the folder hierarchy has associated + Release Configs or Workflow Configs. + + If ``true``: The operation will attempt to delete + everything, including any Release Configs and Workflow + Configs linked to Repositories within the folder hierarchy. + This permanently removes schedules and resources. + """ + + name: str = proto.Field( + proto.STRING, + number=1, + ) + force: bool = proto.Field( + proto.BOOL, + number=2, + ) + + +class DeleteTeamFolderTreeRequest(proto.Message): + r"""``DeleteTeamFolderTree`` request message. + + Attributes: + name (str): + Required. The TeamFolder's name. Format: + projects/{project}/locations/{location}/teamFolders/{team_folder} + force (bool): + Optional. If ``false`` (default): The operation will fail if + any Repository within the folder hierarchy has associated + Release Configs or Workflow Configs. + + If ``true``: The operation will attempt to delete + everything, including any Release Configs and Workflow + Configs linked to Repositories within the folder hierarchy. + This permanently removes schedules and resources. + """ + + name: str = proto.Field( + proto.STRING, + number=1, + ) + force: bool = proto.Field( + proto.BOOL, + number=2, + ) + + +class DeleteFolderTreeMetadata(proto.Message): + r"""Contains metadata about the progress of the DeleteFolderTree + Long-running operations. + + Attributes: + create_time (google.protobuf.timestamp_pb2.Timestamp): + Output only. The time the operation was + created. + end_time (google.protobuf.timestamp_pb2.Timestamp): + Output only. The time the operation finished + running. + target (str): + Output only. Resource name of the target of the operation. + Format: + projects/{project}/locations/{location}/folders/{folder} or + projects/{project}/locations/{location}/teamFolders/{team_folder} + state (google.cloud.dataform_v1beta1.types.DeleteFolderTreeMetadata.State): + Output only. The state of the operation. + percent_complete (int): + Output only. Percent complete of the operation [0, 100]. + """ + + class State(proto.Enum): + r"""Different states of the DeleteFolderTree operation. + + Values: + STATE_UNSPECIFIED (0): + The state is unspecified. + INITIALIZED (1): + The operation was initialized and recorded by + the server, but not yet started. + IN_PROGRESS (2): + The operation is in progress. + SUCCEEDED (3): + The operation has completed successfully. + FAILED (4): + The operation has failed. + """ + + STATE_UNSPECIFIED = 0 + INITIALIZED = 1 + IN_PROGRESS = 2 + SUCCEEDED = 3 + FAILED = 4 + + create_time: timestamp_pb2.Timestamp = proto.Field( + proto.MESSAGE, + number=1, + message=timestamp_pb2.Timestamp, + ) + end_time: timestamp_pb2.Timestamp = proto.Field( + proto.MESSAGE, + number=2, + message=timestamp_pb2.Timestamp, + ) + target: str = proto.Field( + proto.STRING, + number=3, + ) + state: State = proto.Field( + proto.ENUM, + number=4, + enum=State, + ) + percent_complete: int = proto.Field( + proto.INT32, + number=5, + ) + + class QueryFolderContentsRequest(proto.Message): r"""``QueryFolderContents`` request message. Attributes: folder (str): - Required. Name of the folder whose contents to list. Format: - projects/*/locations/*/folders/\* + Required. Resource name of the Folder to list contents for. + Format: projects/*/locations/*/folders/\* page_size (int): Optional. Maximum number of paths to return. The server may return fewer items than @@ -5159,8 +5418,8 @@ class QueryUserRootContentsRequest(proto.Message): Attributes: location (str): - Required. Location of the user root folder whose contents to - list. Format: projects/*/locations/* + Required. Location of the user root folder to list contents + for. Format: projects/*/locations/* page_size (int): Optional. Maximum number of paths to return. The server may return fewer items than @@ -5351,6 +5610,8 @@ class CreateTeamFolderRequest(proto.Message): team_folder (google.cloud.dataform_v1beta1.types.TeamFolder): Required. The TeamFolder to create. team_folder_id (str): + Deprecated: This field is not used. The + resource name is generated automatically. The ID to use for the TeamFolder, which will become the final component of the TeamFolder's resource name. @@ -5428,8 +5689,8 @@ class QueryTeamFolderContentsRequest(proto.Message): Attributes: team_folder (str): - Required. Name of the team_folder whose contents to list. - Format: ``projects/*/locations/*/teamFolders/*``. + Required. Resource name of the TeamFolder to list contents + for. Format: ``projects/*/locations/*/teamFolders/*``. page_size (int): Optional. Maximum number of paths to return. The server may return fewer items than @@ -5553,10 +5814,10 @@ class SearchTeamFoldersRequest(proto.Message): Required. Location in which to query TeamFolders. Format: ``projects/*/locations/*``. page_size (int): - Optional. Maximum number of TeamFolders to - return. The server may return fewer items than - requested. If unspecified, the server will pick - an appropriate default. + Optional. Maximum number of ``TeamFolders`` to return. The + server may return fewer items than requested. If + unspecified, the server will pick a default of ``page_size`` + = 50. page_token (str): Optional. Page token received from a previous ``SearchTeamFolders`` call. Provide this to retrieve the @@ -5788,4 +6049,85 @@ class State(proto.Enum): ) +class DeleteRepositoryLongRunningMetadata(proto.Message): + r"""Represents metadata about the progress of the + DeleteRepository long-running operation. + + Attributes: + create_time (google.protobuf.timestamp_pb2.Timestamp): + Output only. The time the operation was + created. + end_time (google.protobuf.timestamp_pb2.Timestamp): + Output only. The time the operation finished + running. + target (str): + Output only. Server-defined resource path for + the target of the operation. Format: + projects/{project}/locations/{location}/repositories/{repository} + state (google.cloud.dataform_v1beta1.types.DeleteRepositoryLongRunningMetadata.State): + Output only. The state of the operation. + percent_complete (int): + Output only. Percent complete of the operation [0, 100]. + child_resources_count (int): + Output only. The total number of child + resources (Compilation Results, Workflow + Executions) that will be deleted. + remaining_child_resources_count (int): + Output only. The remaining number of child + resources to be deleted. + """ + + class State(proto.Enum): + r"""Different states of the DeleteRepositoryLongRunning + operation. + + Values: + STATE_UNSPECIFIED (0): + The state is unspecified. + RUNNING (1): + The operation is running. + SUCCEEDED (2): + The operation has completed successfully. + FAILED (3): + The operation has failed. + """ + + STATE_UNSPECIFIED = 0 + RUNNING = 1 + SUCCEEDED = 2 + FAILED = 3 + + create_time: timestamp_pb2.Timestamp = proto.Field( + proto.MESSAGE, + number=1, + message=timestamp_pb2.Timestamp, + ) + end_time: timestamp_pb2.Timestamp = proto.Field( + proto.MESSAGE, + number=2, + message=timestamp_pb2.Timestamp, + ) + target: str = proto.Field( + proto.STRING, + number=3, + ) + state: State = proto.Field( + proto.ENUM, + number=4, + enum=State, + ) + percent_complete: int = proto.Field( + proto.INT32, + number=5, + ) + child_resources_count: int = proto.Field( + proto.INT64, + number=6, + ) + remaining_child_resources_count: int = proto.Field( + proto.INT64, + number=7, + ) + + __all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/packages/google-cloud-oracledatabase/samples/generated_samples/oracledatabase_v1_generated_oracle_database_get_goldengate_deployment_type_async.py b/packages/google-cloud-dataform/samples/generated_samples/dataform_v1beta1_generated_dataform_delete_folder_tree_async.py similarity index 71% rename from packages/google-cloud-oracledatabase/samples/generated_samples/oracledatabase_v1_generated_oracle_database_get_goldengate_deployment_type_async.py rename to packages/google-cloud-dataform/samples/generated_samples/dataform_v1beta1_generated_dataform_delete_folder_tree_async.py index 347daf35a32a..1cbd1220f6e8 100644 --- a/packages/google-cloud-oracledatabase/samples/generated_samples/oracledatabase_v1_generated_oracle_database_get_goldengate_deployment_type_async.py +++ b/packages/google-cloud-dataform/samples/generated_samples/dataform_v1beta1_generated_dataform_delete_folder_tree_async.py @@ -15,15 +15,15 @@ # # Generated code. DO NOT EDIT! # -# Snippet for GetGoldengateDeploymentType +# Snippet for DeleteFolderTree # 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-oracledatabase +# python3 -m pip install google-cloud-dataform -# [START oracledatabase_v1_generated_OracleDatabase_GetGoldengateDeploymentType_async] +# [START dataform_v1beta1_generated_Dataform_DeleteFolderTree_async] # This snippet has been automatically generated and should be regarded as a # code template only. # It will require modifications to work: @@ -31,23 +31,27 @@ # - 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 oracledatabase_v1 +from google.cloud import dataform_v1beta1 -async def sample_get_goldengate_deployment_type(): +async def sample_delete_folder_tree(): # Create a client - client = oracledatabase_v1.OracleDatabaseAsyncClient() + client = dataform_v1beta1.DataformAsyncClient() # Initialize request argument(s) - request = oracledatabase_v1.GetGoldengateDeploymentTypeRequest( + request = dataform_v1beta1.DeleteFolderTreeRequest( name="name_value", ) # Make the request - response = await client.get_goldengate_deployment_type(request=request) + operation = await client.delete_folder_tree(request=request) + + print("Waiting for operation to complete...") + + response = await operation.result() # Handle the response print(response) -# [END oracledatabase_v1_generated_OracleDatabase_GetGoldengateDeploymentType_async] +# [END dataform_v1beta1_generated_Dataform_DeleteFolderTree_async] diff --git a/packages/google-cloud-oracledatabase/samples/generated_samples/oracledatabase_v1_generated_oracle_database_get_goldengate_connection_type_sync.py b/packages/google-cloud-dataform/samples/generated_samples/dataform_v1beta1_generated_dataform_delete_folder_tree_sync.py similarity index 72% rename from packages/google-cloud-oracledatabase/samples/generated_samples/oracledatabase_v1_generated_oracle_database_get_goldengate_connection_type_sync.py rename to packages/google-cloud-dataform/samples/generated_samples/dataform_v1beta1_generated_dataform_delete_folder_tree_sync.py index efb71477e349..2de2b44484f8 100644 --- a/packages/google-cloud-oracledatabase/samples/generated_samples/oracledatabase_v1_generated_oracle_database_get_goldengate_connection_type_sync.py +++ b/packages/google-cloud-dataform/samples/generated_samples/dataform_v1beta1_generated_dataform_delete_folder_tree_sync.py @@ -15,15 +15,15 @@ # # Generated code. DO NOT EDIT! # -# Snippet for GetGoldengateConnectionType +# Snippet for DeleteFolderTree # 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-oracledatabase +# python3 -m pip install google-cloud-dataform -# [START oracledatabase_v1_generated_OracleDatabase_GetGoldengateConnectionType_sync] +# [START dataform_v1beta1_generated_Dataform_DeleteFolderTree_sync] # This snippet has been automatically generated and should be regarded as a # code template only. # It will require modifications to work: @@ -31,23 +31,27 @@ # - 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 oracledatabase_v1 +from google.cloud import dataform_v1beta1 -def sample_get_goldengate_connection_type(): +def sample_delete_folder_tree(): # Create a client - client = oracledatabase_v1.OracleDatabaseClient() + client = dataform_v1beta1.DataformClient() # Initialize request argument(s) - request = oracledatabase_v1.GetGoldengateConnectionTypeRequest( + request = dataform_v1beta1.DeleteFolderTreeRequest( name="name_value", ) # Make the request - response = client.get_goldengate_connection_type(request=request) + operation = client.delete_folder_tree(request=request) + + print("Waiting for operation to complete...") + + response = operation.result() # Handle the response print(response) -# [END oracledatabase_v1_generated_OracleDatabase_GetGoldengateConnectionType_sync] +# [END dataform_v1beta1_generated_Dataform_DeleteFolderTree_sync] diff --git a/packages/google-cloud-dataform/samples/generated_samples/dataform_v1beta1_generated_dataform_delete_repository_long_running_async.py b/packages/google-cloud-dataform/samples/generated_samples/dataform_v1beta1_generated_dataform_delete_repository_long_running_async.py new file mode 100644 index 000000000000..6d48ab175e47 --- /dev/null +++ b/packages/google-cloud-dataform/samples/generated_samples/dataform_v1beta1_generated_dataform_delete_repository_long_running_async.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +# Copyright 2026 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 DeleteRepositoryLongRunning +# 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-dataform + + +# [START dataform_v1beta1_generated_Dataform_DeleteRepositoryLongRunning_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 dataform_v1beta1 + + +async def sample_delete_repository_long_running(): + # Create a client + client = dataform_v1beta1.DataformAsyncClient() + + # Initialize request argument(s) + request = dataform_v1beta1.DeleteRepositoryLongRunningRequest( + name="name_value", + ) + + # Make the request + operation = await client.delete_repository_long_running(request=request) + + print("Waiting for operation to complete...") + + response = await operation.result() + + # Handle the response + print(response) + + +# [END dataform_v1beta1_generated_Dataform_DeleteRepositoryLongRunning_async] diff --git a/packages/google-cloud-dataform/samples/generated_samples/dataform_v1beta1_generated_dataform_delete_repository_long_running_sync.py b/packages/google-cloud-dataform/samples/generated_samples/dataform_v1beta1_generated_dataform_delete_repository_long_running_sync.py new file mode 100644 index 000000000000..7741bdf422da --- /dev/null +++ b/packages/google-cloud-dataform/samples/generated_samples/dataform_v1beta1_generated_dataform_delete_repository_long_running_sync.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +# Copyright 2026 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 DeleteRepositoryLongRunning +# 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-dataform + + +# [START dataform_v1beta1_generated_Dataform_DeleteRepositoryLongRunning_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 dataform_v1beta1 + + +def sample_delete_repository_long_running(): + # Create a client + client = dataform_v1beta1.DataformClient() + + # Initialize request argument(s) + request = dataform_v1beta1.DeleteRepositoryLongRunningRequest( + name="name_value", + ) + + # Make the request + operation = client.delete_repository_long_running(request=request) + + print("Waiting for operation to complete...") + + response = operation.result() + + # Handle the response + print(response) + + +# [END dataform_v1beta1_generated_Dataform_DeleteRepositoryLongRunning_sync] diff --git a/packages/google-cloud-dataform/samples/generated_samples/dataform_v1beta1_generated_dataform_delete_team_folder_tree_async.py b/packages/google-cloud-dataform/samples/generated_samples/dataform_v1beta1_generated_dataform_delete_team_folder_tree_async.py new file mode 100644 index 000000000000..7cb1c5204bca --- /dev/null +++ b/packages/google-cloud-dataform/samples/generated_samples/dataform_v1beta1_generated_dataform_delete_team_folder_tree_async.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +# Copyright 2026 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 DeleteTeamFolderTree +# 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-dataform + + +# [START dataform_v1beta1_generated_Dataform_DeleteTeamFolderTree_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 dataform_v1beta1 + + +async def sample_delete_team_folder_tree(): + # Create a client + client = dataform_v1beta1.DataformAsyncClient() + + # Initialize request argument(s) + request = dataform_v1beta1.DeleteTeamFolderTreeRequest( + name="name_value", + ) + + # Make the request + operation = await client.delete_team_folder_tree(request=request) + + print("Waiting for operation to complete...") + + response = await operation.result() + + # Handle the response + print(response) + + +# [END dataform_v1beta1_generated_Dataform_DeleteTeamFolderTree_async] diff --git a/packages/google-cloud-dataform/samples/generated_samples/dataform_v1beta1_generated_dataform_delete_team_folder_tree_sync.py b/packages/google-cloud-dataform/samples/generated_samples/dataform_v1beta1_generated_dataform_delete_team_folder_tree_sync.py new file mode 100644 index 000000000000..536f9324d21f --- /dev/null +++ b/packages/google-cloud-dataform/samples/generated_samples/dataform_v1beta1_generated_dataform_delete_team_folder_tree_sync.py @@ -0,0 +1,57 @@ +# -*- coding: utf-8 -*- +# Copyright 2026 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 DeleteTeamFolderTree +# 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-dataform + + +# [START dataform_v1beta1_generated_Dataform_DeleteTeamFolderTree_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 dataform_v1beta1 + + +def sample_delete_team_folder_tree(): + # Create a client + client = dataform_v1beta1.DataformClient() + + # Initialize request argument(s) + request = dataform_v1beta1.DeleteTeamFolderTreeRequest( + name="name_value", + ) + + # Make the request + operation = client.delete_team_folder_tree(request=request) + + print("Waiting for operation to complete...") + + response = operation.result() + + # Handle the response + print(response) + + +# [END dataform_v1beta1_generated_Dataform_DeleteTeamFolderTree_sync] diff --git a/packages/google-cloud-dataform/samples/generated_samples/snippet_metadata_google.cloud.dataform.v1beta1.json b/packages/google-cloud-dataform/samples/generated_samples/snippet_metadata_google.cloud.dataform.v1beta1.json index 1bfc0730dacd..617b15c45dea 100644 --- a/packages/google-cloud-dataform/samples/generated_samples/snippet_metadata_google.cloud.dataform.v1beta1.json +++ b/packages/google-cloud-dataform/samples/generated_samples/snippet_metadata_google.cloud.dataform.v1beta1.json @@ -2007,6 +2007,175 @@ ], "title": "dataform_v1beta1_generated_dataform_create_workspace_sync.py" }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.dataform_v1beta1.DataformAsyncClient", + "shortName": "DataformAsyncClient" + }, + "fullName": "google.cloud.dataform_v1beta1.DataformAsyncClient.delete_folder_tree", + "method": { + "fullName": "google.cloud.dataform.v1beta1.Dataform.DeleteFolderTree", + "service": { + "fullName": "google.cloud.dataform.v1beta1.Dataform", + "shortName": "Dataform" + }, + "shortName": "DeleteFolderTree" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.dataform_v1beta1.types.DeleteFolderTreeRequest" + }, + { + "name": "name", + "type": "str" + }, + { + "name": "force", + "type": "bool" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, Union[str, bytes]]]" + } + ], + "resultType": "google.api_core.operation_async.AsyncOperation", + "shortName": "delete_folder_tree" + }, + "description": "Sample for DeleteFolderTree", + "file": "dataform_v1beta1_generated_dataform_delete_folder_tree_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "dataform_v1beta1_generated_Dataform_DeleteFolderTree_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": "dataform_v1beta1_generated_dataform_delete_folder_tree_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.dataform_v1beta1.DataformClient", + "shortName": "DataformClient" + }, + "fullName": "google.cloud.dataform_v1beta1.DataformClient.delete_folder_tree", + "method": { + "fullName": "google.cloud.dataform.v1beta1.Dataform.DeleteFolderTree", + "service": { + "fullName": "google.cloud.dataform.v1beta1.Dataform", + "shortName": "Dataform" + }, + "shortName": "DeleteFolderTree" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.dataform_v1beta1.types.DeleteFolderTreeRequest" + }, + { + "name": "name", + "type": "str" + }, + { + "name": "force", + "type": "bool" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, Union[str, bytes]]]" + } + ], + "resultType": "google.api_core.operation.Operation", + "shortName": "delete_folder_tree" + }, + "description": "Sample for DeleteFolderTree", + "file": "dataform_v1beta1_generated_dataform_delete_folder_tree_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "dataform_v1beta1_generated_Dataform_DeleteFolderTree_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": "dataform_v1beta1_generated_dataform_delete_folder_tree_sync.py" + }, { "canonical": true, "clientMethod": { @@ -2317,6 +2486,175 @@ ], "title": "dataform_v1beta1_generated_dataform_delete_release_config_sync.py" }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.dataform_v1beta1.DataformAsyncClient", + "shortName": "DataformAsyncClient" + }, + "fullName": "google.cloud.dataform_v1beta1.DataformAsyncClient.delete_repository_long_running", + "method": { + "fullName": "google.cloud.dataform.v1beta1.Dataform.DeleteRepositoryLongRunning", + "service": { + "fullName": "google.cloud.dataform.v1beta1.Dataform", + "shortName": "Dataform" + }, + "shortName": "DeleteRepositoryLongRunning" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.dataform_v1beta1.types.DeleteRepositoryLongRunningRequest" + }, + { + "name": "name", + "type": "str" + }, + { + "name": "force", + "type": "bool" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, Union[str, bytes]]]" + } + ], + "resultType": "google.api_core.operation_async.AsyncOperation", + "shortName": "delete_repository_long_running" + }, + "description": "Sample for DeleteRepositoryLongRunning", + "file": "dataform_v1beta1_generated_dataform_delete_repository_long_running_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "dataform_v1beta1_generated_Dataform_DeleteRepositoryLongRunning_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": "dataform_v1beta1_generated_dataform_delete_repository_long_running_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.dataform_v1beta1.DataformClient", + "shortName": "DataformClient" + }, + "fullName": "google.cloud.dataform_v1beta1.DataformClient.delete_repository_long_running", + "method": { + "fullName": "google.cloud.dataform.v1beta1.Dataform.DeleteRepositoryLongRunning", + "service": { + "fullName": "google.cloud.dataform.v1beta1.Dataform", + "shortName": "Dataform" + }, + "shortName": "DeleteRepositoryLongRunning" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.dataform_v1beta1.types.DeleteRepositoryLongRunningRequest" + }, + { + "name": "name", + "type": "str" + }, + { + "name": "force", + "type": "bool" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, Union[str, bytes]]]" + } + ], + "resultType": "google.api_core.operation.Operation", + "shortName": "delete_repository_long_running" + }, + "description": "Sample for DeleteRepositoryLongRunning", + "file": "dataform_v1beta1_generated_dataform_delete_repository_long_running_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "dataform_v1beta1_generated_Dataform_DeleteRepositoryLongRunning_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": "dataform_v1beta1_generated_dataform_delete_repository_long_running_sync.py" + }, { "canonical": true, "clientMethod": { @@ -2472,6 +2810,175 @@ ], "title": "dataform_v1beta1_generated_dataform_delete_repository_sync.py" }, + { + "canonical": true, + "clientMethod": { + "async": true, + "client": { + "fullName": "google.cloud.dataform_v1beta1.DataformAsyncClient", + "shortName": "DataformAsyncClient" + }, + "fullName": "google.cloud.dataform_v1beta1.DataformAsyncClient.delete_team_folder_tree", + "method": { + "fullName": "google.cloud.dataform.v1beta1.Dataform.DeleteTeamFolderTree", + "service": { + "fullName": "google.cloud.dataform.v1beta1.Dataform", + "shortName": "Dataform" + }, + "shortName": "DeleteTeamFolderTree" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.dataform_v1beta1.types.DeleteTeamFolderTreeRequest" + }, + { + "name": "name", + "type": "str" + }, + { + "name": "force", + "type": "bool" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, Union[str, bytes]]]" + } + ], + "resultType": "google.api_core.operation_async.AsyncOperation", + "shortName": "delete_team_folder_tree" + }, + "description": "Sample for DeleteTeamFolderTree", + "file": "dataform_v1beta1_generated_dataform_delete_team_folder_tree_async.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "dataform_v1beta1_generated_Dataform_DeleteTeamFolderTree_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": "dataform_v1beta1_generated_dataform_delete_team_folder_tree_async.py" + }, + { + "canonical": true, + "clientMethod": { + "client": { + "fullName": "google.cloud.dataform_v1beta1.DataformClient", + "shortName": "DataformClient" + }, + "fullName": "google.cloud.dataform_v1beta1.DataformClient.delete_team_folder_tree", + "method": { + "fullName": "google.cloud.dataform.v1beta1.Dataform.DeleteTeamFolderTree", + "service": { + "fullName": "google.cloud.dataform.v1beta1.Dataform", + "shortName": "Dataform" + }, + "shortName": "DeleteTeamFolderTree" + }, + "parameters": [ + { + "name": "request", + "type": "google.cloud.dataform_v1beta1.types.DeleteTeamFolderTreeRequest" + }, + { + "name": "name", + "type": "str" + }, + { + "name": "force", + "type": "bool" + }, + { + "name": "retry", + "type": "google.api_core.retry.Retry" + }, + { + "name": "timeout", + "type": "float" + }, + { + "name": "metadata", + "type": "Sequence[Tuple[str, Union[str, bytes]]]" + } + ], + "resultType": "google.api_core.operation.Operation", + "shortName": "delete_team_folder_tree" + }, + "description": "Sample for DeleteTeamFolderTree", + "file": "dataform_v1beta1_generated_dataform_delete_team_folder_tree_sync.py", + "language": "PYTHON", + "origin": "API_DEFINITION", + "regionTag": "dataform_v1beta1_generated_Dataform_DeleteTeamFolderTree_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": "dataform_v1beta1_generated_dataform_delete_team_folder_tree_sync.py" + }, { "canonical": true, "clientMethod": { diff --git a/packages/google-cloud-dataform/tests/unit/gapic/dataform_v1beta1/test_dataform.py b/packages/google-cloud-dataform/tests/unit/gapic/dataform_v1beta1/test_dataform.py index cd9519c1fa14..c3d36adbebbd 100644 --- a/packages/google-cloud-dataform/tests/unit/gapic/dataform_v1beta1/test_dataform.py +++ b/packages/google-cloud-dataform/tests/unit/gapic/dataform_v1beta1/test_dataform.py @@ -2668,6 +2668,365 @@ async def test_delete_team_folder_flattened_error_async(): ) +@pytest.mark.parametrize( + "request_type", + [ + dataform.DeleteTeamFolderTreeRequest(), + {}, + ], +) +def test_delete_team_folder_tree(request_type, transport: str = "grpc"): + client = DataformClient( + 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_team_folder_tree), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.Operation(name="operations/spam") + response = client.delete_team_folder_tree(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = dataform.DeleteTeamFolderTreeRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, future.Future) + + +def test_delete_team_folder_tree_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 = DataformClient( + 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 = dataform.DeleteTeamFolderTreeRequest( + name="name_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.delete_team_folder_tree), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.delete_team_folder_tree(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + request_msg = dataform.DeleteTeamFolderTreeRequest( + name="name_value", + ) + assert args[0] == request_msg + + +def test_delete_team_folder_tree_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = DataformClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.delete_team_folder_tree + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.delete_team_folder_tree + ] = mock_rpc + request = {} + client.delete_team_folder_tree(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + # Operation methods call wrapper_fn to build a cached + # client._transport.operations_client instance on first rpc call. + # Subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + client.delete_team_folder_tree(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_delete_team_folder_tree_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = DataformAsyncClient( + credentials=async_anonymous_credentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.delete_team_folder_tree + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.AsyncMock() + mock_rpc.return_value = mock.Mock() + client._client._transport._wrapped_methods[ + client._client._transport.delete_team_folder_tree + ] = mock_rpc + + request = {} + await client.delete_team_folder_tree(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + # Operation methods call wrapper_fn to build a cached + # client._transport.operations_client instance on first rpc call. + # Subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + await client.delete_team_folder_tree(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +@pytest.mark.parametrize( + "request_type", + [ + dataform.DeleteTeamFolderTreeRequest(), + {}, + ], +) +async def test_delete_team_folder_tree_async( + request_type, transport: str = "grpc_asyncio" +): + client = DataformAsyncClient( + credentials=async_anonymous_credentials(), + 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_team_folder_tree), "__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.delete_team_folder_tree(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = dataform.DeleteTeamFolderTreeRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, future.Future) + + +def test_delete_team_folder_tree_field_headers(): + client = DataformClient( + 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 = dataform.DeleteTeamFolderTreeRequest() + + request.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.delete_team_folder_tree), "__call__" + ) as call: + call.return_value = operations_pb2.Operation(name="operations/op") + client.delete_team_folder_tree(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_team_folder_tree_field_headers_async(): + client = DataformAsyncClient( + credentials=async_anonymous_credentials(), + ) + + # 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 = dataform.DeleteTeamFolderTreeRequest() + + request.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.delete_team_folder_tree), "__call__" + ) as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/op") + ) + await client.delete_team_folder_tree(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_team_folder_tree_flattened(): + client = DataformClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.delete_team_folder_tree), "__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.delete_team_folder_tree( + name="name_value", + force=True, + ) + + # 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 + arg = args[0].force + mock_val = True + assert arg == mock_val + + +def test_delete_team_folder_tree_flattened_error(): + client = DataformClient( + 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_team_folder_tree( + dataform.DeleteTeamFolderTreeRequest(), + name="name_value", + force=True, + ) + + +@pytest.mark.asyncio +async def test_delete_team_folder_tree_flattened_async(): + client = DataformAsyncClient( + credentials=async_anonymous_credentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.delete_team_folder_tree), "__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.delete_team_folder_tree( + name="name_value", + force=True, + ) + + # 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 + arg = args[0].force + mock_val = True + assert arg == mock_val + + +@pytest.mark.asyncio +async def test_delete_team_folder_tree_flattened_error_async(): + client = DataformAsyncClient( + credentials=async_anonymous_credentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + await client.delete_team_folder_tree( + dataform.DeleteTeamFolderTreeRequest(), + name="name_value", + force=True, + ) + + @pytest.mark.parametrize( "request_type", [ @@ -5043,6 +5402,362 @@ async def test_delete_folder_flattened_error_async(): ) +@pytest.mark.parametrize( + "request_type", + [ + dataform.DeleteFolderTreeRequest(), + {}, + ], +) +def test_delete_folder_tree(request_type, transport: str = "grpc"): + client = DataformClient( + 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_folder_tree), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.Operation(name="operations/spam") + response = client.delete_folder_tree(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = dataform.DeleteFolderTreeRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, future.Future) + + +def test_delete_folder_tree_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 = DataformClient( + 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 = dataform.DeleteFolderTreeRequest( + name="name_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.delete_folder_tree), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.delete_folder_tree(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + request_msg = dataform.DeleteFolderTreeRequest( + name="name_value", + ) + assert args[0] == request_msg + + +def test_delete_folder_tree_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = DataformClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.delete_folder_tree in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.delete_folder_tree] = ( + mock_rpc + ) + request = {} + client.delete_folder_tree(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + # Operation methods call wrapper_fn to build a cached + # client._transport.operations_client instance on first rpc call. + # Subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + client.delete_folder_tree(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_delete_folder_tree_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = DataformAsyncClient( + credentials=async_anonymous_credentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.delete_folder_tree + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.AsyncMock() + mock_rpc.return_value = mock.Mock() + client._client._transport._wrapped_methods[ + client._client._transport.delete_folder_tree + ] = mock_rpc + + request = {} + await client.delete_folder_tree(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + # Operation methods call wrapper_fn to build a cached + # client._transport.operations_client instance on first rpc call. + # Subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + await client.delete_folder_tree(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +@pytest.mark.parametrize( + "request_type", + [ + dataform.DeleteFolderTreeRequest(), + {}, + ], +) +async def test_delete_folder_tree_async(request_type, transport: str = "grpc_asyncio"): + client = DataformAsyncClient( + credentials=async_anonymous_credentials(), + 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_folder_tree), "__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.delete_folder_tree(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = dataform.DeleteFolderTreeRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, future.Future) + + +def test_delete_folder_tree_field_headers(): + client = DataformClient( + 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 = dataform.DeleteFolderTreeRequest() + + request.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.delete_folder_tree), "__call__" + ) as call: + call.return_value = operations_pb2.Operation(name="operations/op") + client.delete_folder_tree(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_folder_tree_field_headers_async(): + client = DataformAsyncClient( + credentials=async_anonymous_credentials(), + ) + + # 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 = dataform.DeleteFolderTreeRequest() + + request.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.delete_folder_tree), "__call__" + ) as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/op") + ) + await client.delete_folder_tree(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_folder_tree_flattened(): + client = DataformClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.delete_folder_tree), "__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.delete_folder_tree( + name="name_value", + force=True, + ) + + # 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 + arg = args[0].force + mock_val = True + assert arg == mock_val + + +def test_delete_folder_tree_flattened_error(): + client = DataformClient( + 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_folder_tree( + dataform.DeleteFolderTreeRequest(), + name="name_value", + force=True, + ) + + +@pytest.mark.asyncio +async def test_delete_folder_tree_flattened_async(): + client = DataformAsyncClient( + credentials=async_anonymous_credentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.delete_folder_tree), "__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.delete_folder_tree( + name="name_value", + force=True, + ) + + # 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 + arg = args[0].force + mock_val = True + assert arg == mock_val + + +@pytest.mark.asyncio +async def test_delete_folder_tree_flattened_error_async(): + client = DataformAsyncClient( + credentials=async_anonymous_credentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + await client.delete_folder_tree( + dataform.DeleteFolderTreeRequest(), + name="name_value", + force=True, + ) + + @pytest.mark.parametrize( "request_type", [ @@ -8505,6 +9220,365 @@ async def test_delete_repository_flattened_error_async(): ) +@pytest.mark.parametrize( + "request_type", + [ + dataform.DeleteRepositoryLongRunningRequest(), + {}, + ], +) +def test_delete_repository_long_running(request_type, transport: str = "grpc"): + client = DataformClient( + 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_repository_long_running), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = operations_pb2.Operation(name="operations/spam") + response = client.delete_repository_long_running(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) == 1 + _, args, _ = call.mock_calls[0] + request = dataform.DeleteRepositoryLongRunningRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, future.Future) + + +def test_delete_repository_long_running_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 = DataformClient( + 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 = dataform.DeleteRepositoryLongRunningRequest( + name="name_value", + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.delete_repository_long_running), "__call__" + ) as call: + call.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client.delete_repository_long_running(request=request) + call.assert_called() + _, args, _ = call.mock_calls[0] + request_msg = dataform.DeleteRepositoryLongRunningRequest( + name="name_value", + ) + assert args[0] == request_msg + + +def test_delete_repository_long_running_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = DataformClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.delete_repository_long_running + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.delete_repository_long_running + ] = mock_rpc + request = {} + client.delete_repository_long_running(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + # Operation methods call wrapper_fn to build a cached + # client._transport.operations_client instance on first rpc call. + # Subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + client.delete_repository_long_running(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +async def test_delete_repository_long_running_async_use_cached_wrapped_rpc( + transport: str = "grpc_asyncio", +): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method_async.wrap_method") as wrapper_fn: + client = DataformAsyncClient( + credentials=async_anonymous_credentials(), + transport=transport, + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._client._transport.delete_repository_long_running + in client._client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.AsyncMock() + mock_rpc.return_value = mock.Mock() + client._client._transport._wrapped_methods[ + client._client._transport.delete_repository_long_running + ] = mock_rpc + + request = {} + await client.delete_repository_long_running(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + # Operation methods call wrapper_fn to build a cached + # client._transport.operations_client instance on first rpc call. + # Subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + await client.delete_repository_long_running(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +@pytest.mark.asyncio +@pytest.mark.parametrize( + "request_type", + [ + dataform.DeleteRepositoryLongRunningRequest(), + {}, + ], +) +async def test_delete_repository_long_running_async( + request_type, transport: str = "grpc_asyncio" +): + client = DataformAsyncClient( + credentials=async_anonymous_credentials(), + 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_repository_long_running), "__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.delete_repository_long_running(request) + + # Establish that the underlying gRPC stub method was called. + assert len(call.mock_calls) + _, args, _ = call.mock_calls[0] + request = dataform.DeleteRepositoryLongRunningRequest() + assert args[0] == request + + # Establish that the response is the type that we expect. + assert isinstance(response, future.Future) + + +def test_delete_repository_long_running_field_headers(): + client = DataformClient( + 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 = dataform.DeleteRepositoryLongRunningRequest() + + request.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.delete_repository_long_running), "__call__" + ) as call: + call.return_value = operations_pb2.Operation(name="operations/op") + client.delete_repository_long_running(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_repository_long_running_field_headers_async(): + client = DataformAsyncClient( + credentials=async_anonymous_credentials(), + ) + + # 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 = dataform.DeleteRepositoryLongRunningRequest() + + request.name = "name_value" + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.delete_repository_long_running), "__call__" + ) as call: + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/op") + ) + await client.delete_repository_long_running(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_repository_long_running_flattened(): + client = DataformClient( + credentials=ga_credentials.AnonymousCredentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.delete_repository_long_running), "__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.delete_repository_long_running( + name="name_value", + force=True, + ) + + # 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 + arg = args[0].force + mock_val = True + assert arg == mock_val + + +def test_delete_repository_long_running_flattened_error(): + client = DataformClient( + 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_repository_long_running( + dataform.DeleteRepositoryLongRunningRequest(), + name="name_value", + force=True, + ) + + +@pytest.mark.asyncio +async def test_delete_repository_long_running_flattened_async(): + client = DataformAsyncClient( + credentials=async_anonymous_credentials(), + ) + + # Mock the actual call within the gRPC stub, and fake the request. + with mock.patch.object( + type(client.transport.delete_repository_long_running), "__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.delete_repository_long_running( + name="name_value", + force=True, + ) + + # 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 + arg = args[0].force + mock_val = True + assert arg == mock_val + + +@pytest.mark.asyncio +async def test_delete_repository_long_running_flattened_error_async(): + client = DataformAsyncClient( + credentials=async_anonymous_credentials(), + ) + + # Attempting to call a method with both a request object and flattened + # fields is an error. + with pytest.raises(ValueError): + await client.delete_repository_long_running( + dataform.DeleteRepositoryLongRunningRequest(), + name="name_value", + force=True, + ) + + @pytest.mark.parametrize( "request_type", [ @@ -27304,6 +28378,193 @@ def test_delete_team_folder_rest_flattened_error(transport: str = "rest"): ) +def test_delete_team_folder_tree_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = DataformClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.delete_team_folder_tree + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.delete_team_folder_tree + ] = mock_rpc + + request = {} + client.delete_team_folder_tree(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + # Operation methods build a cached wrapper on first rpc call + # subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + client.delete_team_folder_tree(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_delete_team_folder_tree_rest_required_fields( + request_type=dataform.DeleteTeamFolderTreeRequest, +): + transport_class = transports.DataformRestTransport + + 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_team_folder_tree._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_team_folder_tree._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 = DataformClient( + 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 + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + + response = client.delete_team_folder_tree(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert sorted(expected_params) == sorted(actual_params) + + +def test_delete_team_folder_tree_rest_unset_required_fields(): + transport = transports.DataformRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.delete_team_folder_tree._get_unset_required_fields({}) + assert set(unset_fields) == (set(()) & set(("name",))) + + +def test_delete_team_folder_tree_rest_flattened(): + client = DataformClient( + 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/teamFolders/sample3" + } + + # get truthy value for each flattened field + mock_args = dict( + name="name_value", + force=True, + ) + 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 + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + + client.delete_team_folder_tree(**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/v1beta1/{name=projects/*/locations/*/teamFolders/*}:deleteTree" + % client.transport._host, + args[1], + ) + + +def test_delete_team_folder_tree_rest_flattened_error(transport: str = "rest"): + client = DataformClient( + 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_team_folder_tree( + dataform.DeleteTeamFolderTreeRequest(), + name="name_value", + force=True, + ) + + def test_query_team_folder_contents_rest_use_cached_wrapped_rpc(): # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, # instead of constructing them on each call @@ -28501,6 +29762,190 @@ def test_delete_folder_rest_flattened_error(transport: str = "rest"): ) +def test_delete_folder_tree_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = DataformClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.delete_folder_tree in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[client._transport.delete_folder_tree] = ( + mock_rpc + ) + + request = {} + client.delete_folder_tree(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + # Operation methods build a cached wrapper on first rpc call + # subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + client.delete_folder_tree(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_delete_folder_tree_rest_required_fields( + request_type=dataform.DeleteFolderTreeRequest, +): + transport_class = transports.DataformRestTransport + + 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_folder_tree._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_folder_tree._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 = DataformClient( + 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 + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + + response = client.delete_folder_tree(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert sorted(expected_params) == sorted(actual_params) + + +def test_delete_folder_tree_rest_unset_required_fields(): + transport = transports.DataformRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.delete_folder_tree._get_unset_required_fields({}) + assert set(unset_fields) == (set(()) & set(("name",))) + + +def test_delete_folder_tree_rest_flattened(): + client = DataformClient( + 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/folders/sample3"} + + # get truthy value for each flattened field + mock_args = dict( + name="name_value", + force=True, + ) + 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 + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + + client.delete_folder_tree(**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/v1beta1/{name=projects/*/locations/*/folders/*}:deleteTree" + % client.transport._host, + args[1], + ) + + +def test_delete_folder_tree_rest_flattened_error(transport: str = "rest"): + client = DataformClient( + 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_folder_tree( + dataform.DeleteFolderTreeRequest(), + name="name_value", + force=True, + ) + + def test_query_folder_contents_rest_use_cached_wrapped_rpc(): # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, # instead of constructing them on each call @@ -30231,6 +31676,195 @@ def test_delete_repository_rest_flattened_error(transport: str = "rest"): ) +def test_delete_repository_long_running_rest_use_cached_wrapped_rpc(): + # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, + # instead of constructing them on each call + with mock.patch("google.api_core.gapic_v1.method.wrap_method") as wrapper_fn: + client = DataformClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Should wrap all calls on client creation + assert wrapper_fn.call_count > 0 + wrapper_fn.reset_mock() + + # Ensure method has been cached + assert ( + client._transport.delete_repository_long_running + in client._transport._wrapped_methods + ) + + # Replace cached wrapped function with mock + mock_rpc = mock.Mock() + mock_rpc.return_value.name = ( + "foo" # operation_request.operation in compute client(s) expect a string. + ) + client._transport._wrapped_methods[ + client._transport.delete_repository_long_running + ] = mock_rpc + + request = {} + client.delete_repository_long_running(request) + + # Establish that the underlying gRPC stub method was called. + assert mock_rpc.call_count == 1 + + # Operation methods build a cached wrapper on first rpc call + # subsequent calls should use the cached wrapper + wrapper_fn.reset_mock() + + client.delete_repository_long_running(request) + + # Establish that a new wrapper was not created for this call + assert wrapper_fn.call_count == 0 + assert mock_rpc.call_count == 2 + + +def test_delete_repository_long_running_rest_required_fields( + request_type=dataform.DeleteRepositoryLongRunningRequest, +): + transport_class = transports.DataformRestTransport + + 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_repository_long_running._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_repository_long_running._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 = DataformClient( + 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 + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + + response = client.delete_repository_long_running(request) + + expected_params = [("$alt", "json;enum-encoding=int")] + actual_params = req.call_args.kwargs["params"] + assert sorted(expected_params) == sorted(actual_params) + + +def test_delete_repository_long_running_rest_unset_required_fields(): + transport = transports.DataformRestTransport( + credentials=ga_credentials.AnonymousCredentials + ) + + unset_fields = transport.delete_repository_long_running._get_unset_required_fields( + {} + ) + assert set(unset_fields) == (set(()) & set(("name",))) + + +def test_delete_repository_long_running_rest_flattened(): + client = DataformClient( + 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/repositories/sample3" + } + + # get truthy value for each flattened field + mock_args = dict( + name="name_value", + force=True, + ) + 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 + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + + client.delete_repository_long_running(**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/v1beta1/{name=projects/*/locations/*/repositories/*}:deleteLongRunning" + % client.transport._host, + args[1], + ) + + +def test_delete_repository_long_running_rest_flattened_error(transport: str = "rest"): + client = DataformClient( + 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_repository_long_running( + dataform.DeleteRepositoryLongRunningRequest(), + name="name_value", + force=True, + ) + + def test_move_repository_rest_use_cached_wrapped_rpc(): # Clients should use _prep_wrapped_messages to create cached wrapped rpcs, # instead of constructing them on each call @@ -33319,6 +34953,7 @@ def test_query_directory_contents_rest_required_fields( "page_size", "page_token", "path", + "view", ) ) jsonified_request.update(unset_fields) @@ -33381,6 +35016,7 @@ def test_query_directory_contents_rest_unset_required_fields(): "pageSize", "pageToken", "path", + "view", ) ) & set(("workspace",)) @@ -39692,6 +41328,28 @@ def test_delete_team_folder_empty_call_grpc(): assert args[0] == request_msg +# This test is a coverage failsafe to make sure that totally empty calls, +# i.e. request == None and no flattened fields passed, work. +def test_delete_team_folder_tree_empty_call_grpc(): + client = DataformClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Mock the actual call, and fake the request. + with mock.patch.object( + type(client.transport.delete_team_folder_tree), "__call__" + ) as call: + call.return_value = operations_pb2.Operation(name="operations/op") + client.delete_team_folder_tree(request=None) + + # Establish that the underlying stub method was called. + call.assert_called() + _, args, _ = call.mock_calls[0] + request_msg = dataform.DeleteTeamFolderTreeRequest() + assert args[0] == request_msg + + # This test is a coverage failsafe to make sure that totally empty calls, # i.e. request == None and no flattened fields passed, work. def test_query_team_folder_contents_empty_call_grpc(): @@ -39816,6 +41474,28 @@ def test_delete_folder_empty_call_grpc(): assert args[0] == request_msg +# This test is a coverage failsafe to make sure that totally empty calls, +# i.e. request == None and no flattened fields passed, work. +def test_delete_folder_tree_empty_call_grpc(): + client = DataformClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Mock the actual call, and fake the request. + with mock.patch.object( + type(client.transport.delete_folder_tree), "__call__" + ) as call: + call.return_value = operations_pb2.Operation(name="operations/op") + client.delete_folder_tree(request=None) + + # Establish that the underlying stub method was called. + call.assert_called() + _, args, _ = call.mock_calls[0] + request_msg = dataform.DeleteFolderTreeRequest() + assert args[0] == request_msg + + # This test is a coverage failsafe to make sure that totally empty calls, # i.e. request == None and no flattened fields passed, work. def test_query_folder_contents_empty_call_grpc(): @@ -39988,6 +41668,28 @@ def test_delete_repository_empty_call_grpc(): assert args[0] == request_msg +# This test is a coverage failsafe to make sure that totally empty calls, +# i.e. request == None and no flattened fields passed, work. +def test_delete_repository_long_running_empty_call_grpc(): + client = DataformClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="grpc", + ) + + # Mock the actual call, and fake the request. + with mock.patch.object( + type(client.transport.delete_repository_long_running), "__call__" + ) as call: + call.return_value = operations_pb2.Operation(name="operations/op") + client.delete_repository_long_running(request=None) + + # Establish that the underlying stub method was called. + call.assert_called() + _, args, _ = call.mock_calls[0] + request_msg = dataform.DeleteRepositoryLongRunningRequest() + assert args[0] == request_msg + + # This test is a coverage failsafe to make sure that totally empty calls, # i.e. request == None and no flattened fields passed, work. def test_move_repository_empty_call_grpc(): @@ -41243,6 +42945,32 @@ async def test_delete_team_folder_empty_call_grpc_asyncio(): assert args[0] == request_msg +# This test is a coverage failsafe to make sure that totally empty calls, +# i.e. request == None and no flattened fields passed, work. +@pytest.mark.asyncio +async def test_delete_team_folder_tree_empty_call_grpc_asyncio(): + client = DataformAsyncClient( + credentials=async_anonymous_credentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call, and fake the request. + with mock.patch.object( + type(client.transport.delete_team_folder_tree), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/spam") + ) + await client.delete_team_folder_tree(request=None) + + # Establish that the underlying stub method was called. + call.assert_called() + _, args, _ = call.mock_calls[0] + request_msg = dataform.DeleteTeamFolderTreeRequest() + assert args[0] == request_msg + + # This test is a coverage failsafe to make sure that totally empty calls, # i.e. request == None and no flattened fields passed, work. @pytest.mark.asyncio @@ -41414,6 +43142,32 @@ async def test_delete_folder_empty_call_grpc_asyncio(): assert args[0] == request_msg +# This test is a coverage failsafe to make sure that totally empty calls, +# i.e. request == None and no flattened fields passed, work. +@pytest.mark.asyncio +async def test_delete_folder_tree_empty_call_grpc_asyncio(): + client = DataformAsyncClient( + credentials=async_anonymous_credentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call, and fake the request. + with mock.patch.object( + type(client.transport.delete_folder_tree), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/spam") + ) + await client.delete_folder_tree(request=None) + + # Establish that the underlying stub method was called. + call.assert_called() + _, args, _ = call.mock_calls[0] + request_msg = dataform.DeleteFolderTreeRequest() + assert args[0] == request_msg + + # This test is a coverage failsafe to make sure that totally empty calls, # i.e. request == None and no flattened fields passed, work. @pytest.mark.asyncio @@ -41653,6 +43407,32 @@ async def test_delete_repository_empty_call_grpc_asyncio(): assert args[0] == request_msg +# This test is a coverage failsafe to make sure that totally empty calls, +# i.e. request == None and no flattened fields passed, work. +@pytest.mark.asyncio +async def test_delete_repository_long_running_empty_call_grpc_asyncio(): + client = DataformAsyncClient( + credentials=async_anonymous_credentials(), + transport="grpc_asyncio", + ) + + # Mock the actual call, and fake the request. + with mock.patch.object( + type(client.transport.delete_repository_long_running), "__call__" + ) as call: + # Designate an appropriate return value for the call. + call.return_value = grpc_helpers_async.FakeUnaryUnaryCall( + operations_pb2.Operation(name="operations/spam") + ) + await client.delete_repository_long_running(request=None) + + # Establish that the underlying stub method was called. + call.assert_called() + _, args, _ = call.mock_calls[0] + request_msg = dataform.DeleteRepositoryLongRunningRequest() + assert args[0] == request_msg + + # This test is a coverage failsafe to make sure that totally empty calls, # i.e. request == None and no flattened fields passed, work. @pytest.mark.asyncio @@ -43785,6 +45565,130 @@ def test_delete_team_folder_rest_interceptors(null_interceptor): pre.assert_called_once() +def test_delete_team_folder_tree_rest_bad_request( + request_type=dataform.DeleteTeamFolderTreeRequest, +): + client = DataformClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + # send a request that will satisfy transcoding + request_init = {"name": "projects/sample1/locations/sample2/teamFolders/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 = mock.Mock() + json_return_value = "" + response_value.json = mock.Mock(return_value={}) + response_value.status_code = 400 + response_value.request = mock.Mock() + req.return_value = response_value + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + client.delete_team_folder_tree(request) + + +@pytest.mark.parametrize( + "request_type", + [ + dataform.DeleteTeamFolderTreeRequest, + dict, + ], +) +def test_delete_team_folder_tree_rest_call_success(request_type): + client = DataformClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + # send a request that will satisfy transcoding + request_init = {"name": "projects/sample1/locations/sample2/teamFolders/sample3"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = operations_pb2.Operation(name="operations/spam") + + # Wrap the value into a proper Response obj + response_value = mock.Mock() + 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 + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + response = client.delete_team_folder_tree(request) + + # Establish that the response is the type that we expect. + json_return_value = json_format.MessageToJson(return_value) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_delete_team_folder_tree_rest_interceptors(null_interceptor): + transport = transports.DataformRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None if null_interceptor else transports.DataformRestInterceptor(), + ) + client = DataformClient(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.DataformRestInterceptor, "post_delete_team_folder_tree" + ) as post, + mock.patch.object( + transports.DataformRestInterceptor, + "post_delete_team_folder_tree_with_metadata", + ) as post_with_metadata, + mock.patch.object( + transports.DataformRestInterceptor, "pre_delete_team_folder_tree" + ) as pre, + ): + pre.assert_not_called() + post.assert_not_called() + post_with_metadata.assert_not_called() + pb_message = dataform.DeleteTeamFolderTreeRequest.pb( + dataform.DeleteTeamFolderTreeRequest() + ) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = mock.Mock() + req.return_value.status_code = 200 + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + return_value = json_format.MessageToJson(operations_pb2.Operation()) + req.return_value.content = return_value + + request = dataform.DeleteTeamFolderTreeRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = operations_pb2.Operation() + post_with_metadata.return_value = operations_pb2.Operation(), metadata + + client.delete_team_folder_tree( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + post_with_metadata.assert_called_once() + + def test_query_team_folder_contents_rest_bad_request( request_type=dataform.QueryTeamFolderContentsRequest, ): @@ -44715,6 +46619,129 @@ def test_delete_folder_rest_interceptors(null_interceptor): pre.assert_called_once() +def test_delete_folder_tree_rest_bad_request( + request_type=dataform.DeleteFolderTreeRequest, +): + client = DataformClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + # send a request that will satisfy transcoding + request_init = {"name": "projects/sample1/locations/sample2/folders/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 = mock.Mock() + json_return_value = "" + response_value.json = mock.Mock(return_value={}) + response_value.status_code = 400 + response_value.request = mock.Mock() + req.return_value = response_value + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + client.delete_folder_tree(request) + + +@pytest.mark.parametrize( + "request_type", + [ + dataform.DeleteFolderTreeRequest, + dict, + ], +) +def test_delete_folder_tree_rest_call_success(request_type): + client = DataformClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + # send a request that will satisfy transcoding + request_init = {"name": "projects/sample1/locations/sample2/folders/sample3"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = operations_pb2.Operation(name="operations/spam") + + # Wrap the value into a proper Response obj + response_value = mock.Mock() + 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 + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + response = client.delete_folder_tree(request) + + # Establish that the response is the type that we expect. + json_return_value = json_format.MessageToJson(return_value) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_delete_folder_tree_rest_interceptors(null_interceptor): + transport = transports.DataformRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None if null_interceptor else transports.DataformRestInterceptor(), + ) + client = DataformClient(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.DataformRestInterceptor, "post_delete_folder_tree" + ) as post, + mock.patch.object( + transports.DataformRestInterceptor, "post_delete_folder_tree_with_metadata" + ) as post_with_metadata, + mock.patch.object( + transports.DataformRestInterceptor, "pre_delete_folder_tree" + ) as pre, + ): + pre.assert_not_called() + post.assert_not_called() + post_with_metadata.assert_not_called() + pb_message = dataform.DeleteFolderTreeRequest.pb( + dataform.DeleteFolderTreeRequest() + ) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = mock.Mock() + req.return_value.status_code = 200 + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + return_value = json_format.MessageToJson(operations_pb2.Operation()) + req.return_value.content = return_value + + request = dataform.DeleteFolderTreeRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = operations_pb2.Operation() + post_with_metadata.return_value = operations_pb2.Operation(), metadata + + client.delete_folder_tree( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + post_with_metadata.assert_called_once() + + def test_query_folder_contents_rest_bad_request( request_type=dataform.QueryFolderContentsRequest, ): @@ -45424,11 +47451,13 @@ def test_create_repository_rest_call_success(request_type): "git_remote_settings": { "url": "url_value", "default_branch": "default_branch_value", + "effective_default_branch": "effective_default_branch_value", "authentication_token_secret_version": "authentication_token_secret_version_value", "ssh_authentication_config": { "user_private_key_secret_version": "user_private_key_secret_version_value", "host_public_key": "host_public_key_value", }, + "git_repository_link": "git_repository_link_value", "token_status": 1, }, "npmrc_environment_variables_secret_version": "npmrc_environment_variables_secret_version_value", @@ -45675,11 +47704,13 @@ def test_update_repository_rest_call_success(request_type): "git_remote_settings": { "url": "url_value", "default_branch": "default_branch_value", + "effective_default_branch": "effective_default_branch_value", "authentication_token_secret_version": "authentication_token_secret_version_value", "ssh_authentication_config": { "user_private_key_secret_version": "user_private_key_secret_version_value", "host_public_key": "host_public_key_value", }, + "git_repository_link": "git_repository_link_value", "token_status": 1, }, "npmrc_environment_variables_secret_version": "npmrc_environment_variables_secret_version_value", @@ -45977,6 +48008,130 @@ def test_delete_repository_rest_interceptors(null_interceptor): pre.assert_called_once() +def test_delete_repository_long_running_rest_bad_request( + request_type=dataform.DeleteRepositoryLongRunningRequest, +): + client = DataformClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + # send a request that will satisfy transcoding + request_init = {"name": "projects/sample1/locations/sample2/repositories/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 = mock.Mock() + json_return_value = "" + response_value.json = mock.Mock(return_value={}) + response_value.status_code = 400 + response_value.request = mock.Mock() + req.return_value = response_value + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + client.delete_repository_long_running(request) + + +@pytest.mark.parametrize( + "request_type", + [ + dataform.DeleteRepositoryLongRunningRequest, + dict, + ], +) +def test_delete_repository_long_running_rest_call_success(request_type): + client = DataformClient( + credentials=ga_credentials.AnonymousCredentials(), transport="rest" + ) + + # send a request that will satisfy transcoding + request_init = {"name": "projects/sample1/locations/sample2/repositories/sample3"} + request = request_type(**request_init) + + # Mock the http request call within the method and fake a response. + with mock.patch.object(type(client.transport._session), "request") as req: + # Designate an appropriate value for the returned response. + return_value = operations_pb2.Operation(name="operations/spam") + + # Wrap the value into a proper Response obj + response_value = mock.Mock() + 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 + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + response = client.delete_repository_long_running(request) + + # Establish that the response is the type that we expect. + json_return_value = json_format.MessageToJson(return_value) + + +@pytest.mark.parametrize("null_interceptor", [True, False]) +def test_delete_repository_long_running_rest_interceptors(null_interceptor): + transport = transports.DataformRestTransport( + credentials=ga_credentials.AnonymousCredentials(), + interceptor=None if null_interceptor else transports.DataformRestInterceptor(), + ) + client = DataformClient(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.DataformRestInterceptor, "post_delete_repository_long_running" + ) as post, + mock.patch.object( + transports.DataformRestInterceptor, + "post_delete_repository_long_running_with_metadata", + ) as post_with_metadata, + mock.patch.object( + transports.DataformRestInterceptor, "pre_delete_repository_long_running" + ) as pre, + ): + pre.assert_not_called() + post.assert_not_called() + post_with_metadata.assert_not_called() + pb_message = dataform.DeleteRepositoryLongRunningRequest.pb( + dataform.DeleteRepositoryLongRunningRequest() + ) + transcode.return_value = { + "method": "post", + "uri": "my_uri", + "body": pb_message, + "query_params": pb_message, + } + + req.return_value = mock.Mock() + req.return_value.status_code = 200 + req.return_value.headers = {"header-1": "value-1", "header-2": "value-2"} + return_value = json_format.MessageToJson(operations_pb2.Operation()) + req.return_value.content = return_value + + request = dataform.DeleteRepositoryLongRunningRequest() + metadata = [ + ("key", "val"), + ("cephalopod", "squid"), + ] + pre.return_value = request, metadata + post.return_value = operations_pb2.Operation() + post_with_metadata.return_value = operations_pb2.Operation(), metadata + + client.delete_repository_long_running( + request, + metadata=[ + ("key", "val"), + ("cephalopod", "squid"), + ], + ) + + pre.assert_called_once() + post.assert_called_once() + post_with_metadata.assert_called_once() + + def test_move_repository_rest_bad_request(request_type=dataform.MoveRepositoryRequest): client = DataformClient( credentials=ga_credentials.AnonymousCredentials(), transport="rest" @@ -54225,6 +56380,27 @@ def test_delete_team_folder_empty_call_rest(): assert args[0] == request_msg +# This test is a coverage failsafe to make sure that totally empty calls, +# i.e. request == None and no flattened fields passed, work. +def test_delete_team_folder_tree_empty_call_rest(): + client = DataformClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the actual call, and fake the request. + with mock.patch.object( + type(client.transport.delete_team_folder_tree), "__call__" + ) as call: + client.delete_team_folder_tree(request=None) + + # Establish that the underlying stub method was called. + call.assert_called() + _, args, _ = call.mock_calls[0] + request_msg = dataform.DeleteTeamFolderTreeRequest() + assert args[0] == request_msg + + # This test is a coverage failsafe to make sure that totally empty calls, # i.e. request == None and no flattened fields passed, work. def test_query_team_folder_contents_empty_call_rest(): @@ -54343,6 +56519,27 @@ def test_delete_folder_empty_call_rest(): assert args[0] == request_msg +# This test is a coverage failsafe to make sure that totally empty calls, +# i.e. request == None and no flattened fields passed, work. +def test_delete_folder_tree_empty_call_rest(): + client = DataformClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the actual call, and fake the request. + with mock.patch.object( + type(client.transport.delete_folder_tree), "__call__" + ) as call: + client.delete_folder_tree(request=None) + + # Establish that the underlying stub method was called. + call.assert_called() + _, args, _ = call.mock_calls[0] + request_msg = dataform.DeleteFolderTreeRequest() + assert args[0] == request_msg + + # This test is a coverage failsafe to make sure that totally empty calls, # i.e. request == None and no flattened fields passed, work. def test_query_folder_contents_empty_call_rest(): @@ -54507,6 +56704,27 @@ def test_delete_repository_empty_call_rest(): assert args[0] == request_msg +# This test is a coverage failsafe to make sure that totally empty calls, +# i.e. request == None and no flattened fields passed, work. +def test_delete_repository_long_running_empty_call_rest(): + client = DataformClient( + credentials=ga_credentials.AnonymousCredentials(), + transport="rest", + ) + + # Mock the actual call, and fake the request. + with mock.patch.object( + type(client.transport.delete_repository_long_running), "__call__" + ) as call: + client.delete_repository_long_running(request=None) + + # Establish that the underlying stub method was called. + call.assert_called() + _, args, _ = call.mock_calls[0] + request_msg = dataform.DeleteRepositoryLongRunningRequest() + assert args[0] == request_msg + + # This test is a coverage failsafe to make sure that totally empty calls, # i.e. request == None and no flattened fields passed, work. def test_move_repository_empty_call_rest(): @@ -55634,12 +57852,14 @@ def test_dataform_base_transport(): "create_team_folder", "update_team_folder", "delete_team_folder", + "delete_team_folder_tree", "query_team_folder_contents", "search_team_folders", "get_folder", "create_folder", "update_folder", "delete_folder", + "delete_folder_tree", "query_folder_contents", "query_user_root_contents", "move_folder", @@ -55648,6 +57868,7 @@ def test_dataform_base_transport(): "create_repository", "update_repository", "delete_repository", + "delete_repository_long_running", "move_repository", "commit_repository_changes", "read_repository_file", @@ -55998,6 +58219,9 @@ def test_dataform_client_transport_session_collision(transport_name): session1 = client1.transport.delete_team_folder._session session2 = client2.transport.delete_team_folder._session assert session1 != session2 + session1 = client1.transport.delete_team_folder_tree._session + session2 = client2.transport.delete_team_folder_tree._session + assert session1 != session2 session1 = client1.transport.query_team_folder_contents._session session2 = client2.transport.query_team_folder_contents._session assert session1 != session2 @@ -56016,6 +58240,9 @@ def test_dataform_client_transport_session_collision(transport_name): session1 = client1.transport.delete_folder._session session2 = client2.transport.delete_folder._session assert session1 != session2 + session1 = client1.transport.delete_folder_tree._session + session2 = client2.transport.delete_folder_tree._session + assert session1 != session2 session1 = client1.transport.query_folder_contents._session session2 = client2.transport.query_folder_contents._session assert session1 != session2 @@ -56040,6 +58267,9 @@ def test_dataform_client_transport_session_collision(transport_name): session1 = client1.transport.delete_repository._session session2 = client2.transport.delete_repository._session assert session1 != session2 + session1 = client1.transport.delete_repository_long_running._session + session2 = client2.transport.delete_repository_long_running._session + assert session1 != session2 session1 = client1.transport.move_repository._session session2 = client2.transport.move_repository._session assert session1 != session2 @@ -56497,10 +58727,41 @@ def test_parse_folder_path(): assert expected == actual -def test_notebook_runtime_template_path(): +def test_git_repository_link_path(): project = "squid" location = "clam" - notebook_runtime_template = "whelk" + connection = "whelk" + git_repository_link = "octopus" + expected = "projects/{project}/locations/{location}/connections/{connection}/gitRepositoryLinks/{git_repository_link}".format( + project=project, + location=location, + connection=connection, + git_repository_link=git_repository_link, + ) + actual = DataformClient.git_repository_link_path( + project, location, connection, git_repository_link + ) + assert expected == actual + + +def test_parse_git_repository_link_path(): + expected = { + "project": "oyster", + "location": "nudibranch", + "connection": "cuttlefish", + "git_repository_link": "mussel", + } + path = DataformClient.git_repository_link_path(**expected) + + # Check that the path construction is reversible. + actual = DataformClient.parse_git_repository_link_path(path) + assert expected == actual + + +def test_notebook_runtime_template_path(): + project = "winkle" + location = "nautilus" + notebook_runtime_template = "scallop" expected = "projects/{project}/locations/{location}/notebookRuntimeTemplates/{notebook_runtime_template}".format( project=project, location=location, @@ -56514,9 +58775,9 @@ def test_notebook_runtime_template_path(): def test_parse_notebook_runtime_template_path(): expected = { - "project": "octopus", - "location": "oyster", - "notebook_runtime_template": "nudibranch", + "project": "abalone", + "location": "squid", + "notebook_runtime_template": "clam", } path = DataformClient.notebook_runtime_template_path(**expected) @@ -56526,10 +58787,10 @@ def test_parse_notebook_runtime_template_path(): def test_release_config_path(): - project = "cuttlefish" - location = "mussel" - repository = "winkle" - release_config = "nautilus" + project = "whelk" + location = "octopus" + repository = "oyster" + release_config = "nudibranch" expected = "projects/{project}/locations/{location}/repositories/{repository}/releaseConfigs/{release_config}".format( project=project, location=location, @@ -56544,10 +58805,10 @@ def test_release_config_path(): def test_parse_release_config_path(): expected = { - "project": "scallop", - "location": "abalone", - "repository": "squid", - "release_config": "clam", + "project": "cuttlefish", + "location": "mussel", + "repository": "winkle", + "release_config": "nautilus", } path = DataformClient.release_config_path(**expected) @@ -56557,9 +58818,9 @@ def test_parse_release_config_path(): def test_repository_path(): - project = "whelk" - location = "octopus" - repository = "oyster" + project = "scallop" + location = "abalone" + repository = "squid" expected = ( "projects/{project}/locations/{location}/repositories/{repository}".format( project=project, @@ -56573,9 +58834,9 @@ def test_repository_path(): def test_parse_repository_path(): expected = { - "project": "nudibranch", - "location": "cuttlefish", - "repository": "mussel", + "project": "clam", + "location": "whelk", + "repository": "octopus", } path = DataformClient.repository_path(**expected) @@ -56585,9 +58846,9 @@ def test_parse_repository_path(): def test_secret_version_path(): - project = "winkle" - secret = "nautilus" - version = "scallop" + project = "oyster" + secret = "nudibranch" + version = "cuttlefish" expected = "projects/{project}/secrets/{secret}/versions/{version}".format( project=project, secret=secret, @@ -56599,9 +58860,9 @@ def test_secret_version_path(): def test_parse_secret_version_path(): expected = { - "project": "abalone", - "secret": "squid", - "version": "clam", + "project": "mussel", + "secret": "winkle", + "version": "nautilus", } path = DataformClient.secret_version_path(**expected) @@ -56611,9 +58872,9 @@ def test_parse_secret_version_path(): def test_team_folder_path(): - project = "whelk" - location = "octopus" - team_folder = "oyster" + project = "scallop" + location = "abalone" + team_folder = "squid" expected = ( "projects/{project}/locations/{location}/teamFolders/{team_folder}".format( project=project, @@ -56627,9 +58888,9 @@ def test_team_folder_path(): def test_parse_team_folder_path(): expected = { - "project": "nudibranch", - "location": "cuttlefish", - "team_folder": "mussel", + "project": "clam", + "location": "whelk", + "team_folder": "octopus", } path = DataformClient.team_folder_path(**expected) @@ -56639,10 +58900,10 @@ def test_parse_team_folder_path(): def test_workflow_config_path(): - project = "winkle" - location = "nautilus" - repository = "scallop" - workflow_config = "abalone" + project = "oyster" + location = "nudibranch" + repository = "cuttlefish" + workflow_config = "mussel" expected = "projects/{project}/locations/{location}/repositories/{repository}/workflowConfigs/{workflow_config}".format( project=project, location=location, @@ -56657,10 +58918,10 @@ def test_workflow_config_path(): def test_parse_workflow_config_path(): expected = { - "project": "squid", - "location": "clam", - "repository": "whelk", - "workflow_config": "octopus", + "project": "winkle", + "location": "nautilus", + "repository": "scallop", + "workflow_config": "abalone", } path = DataformClient.workflow_config_path(**expected) @@ -56670,10 +58931,10 @@ def test_parse_workflow_config_path(): def test_workflow_invocation_path(): - project = "oyster" - location = "nudibranch" - repository = "cuttlefish" - workflow_invocation = "mussel" + project = "squid" + location = "clam" + repository = "whelk" + workflow_invocation = "octopus" expected = "projects/{project}/locations/{location}/repositories/{repository}/workflowInvocations/{workflow_invocation}".format( project=project, location=location, @@ -56688,10 +58949,10 @@ def test_workflow_invocation_path(): def test_parse_workflow_invocation_path(): expected = { - "project": "winkle", - "location": "nautilus", - "repository": "scallop", - "workflow_invocation": "abalone", + "project": "oyster", + "location": "nudibranch", + "repository": "cuttlefish", + "workflow_invocation": "mussel", } path = DataformClient.workflow_invocation_path(**expected) @@ -56701,10 +58962,10 @@ def test_parse_workflow_invocation_path(): def test_workspace_path(): - project = "squid" - location = "clam" - repository = "whelk" - workspace = "octopus" + project = "winkle" + location = "nautilus" + repository = "scallop" + workspace = "abalone" expected = "projects/{project}/locations/{location}/repositories/{repository}/workspaces/{workspace}".format( project=project, location=location, @@ -56717,10 +58978,10 @@ def test_workspace_path(): def test_parse_workspace_path(): expected = { - "project": "oyster", - "location": "nudibranch", - "repository": "cuttlefish", - "workspace": "mussel", + "project": "squid", + "location": "clam", + "repository": "whelk", + "workspace": "octopus", } path = DataformClient.workspace_path(**expected) @@ -56730,7 +58991,7 @@ def test_parse_workspace_path(): def test_common_billing_account_path(): - billing_account = "winkle" + billing_account = "oyster" expected = "billingAccounts/{billing_account}".format( billing_account=billing_account, ) @@ -56740,7 +59001,7 @@ def test_common_billing_account_path(): def test_parse_common_billing_account_path(): expected = { - "billing_account": "nautilus", + "billing_account": "nudibranch", } path = DataformClient.common_billing_account_path(**expected) @@ -56750,7 +59011,7 @@ def test_parse_common_billing_account_path(): def test_common_folder_path(): - folder = "scallop" + folder = "cuttlefish" expected = "folders/{folder}".format( folder=folder, ) @@ -56760,7 +59021,7 @@ def test_common_folder_path(): def test_parse_common_folder_path(): expected = { - "folder": "abalone", + "folder": "mussel", } path = DataformClient.common_folder_path(**expected) @@ -56770,7 +59031,7 @@ def test_parse_common_folder_path(): def test_common_organization_path(): - organization = "squid" + organization = "winkle" expected = "organizations/{organization}".format( organization=organization, ) @@ -56780,7 +59041,7 @@ def test_common_organization_path(): def test_parse_common_organization_path(): expected = { - "organization": "clam", + "organization": "nautilus", } path = DataformClient.common_organization_path(**expected) @@ -56790,7 +59051,7 @@ def test_parse_common_organization_path(): def test_common_project_path(): - project = "whelk" + project = "scallop" expected = "projects/{project}".format( project=project, ) @@ -56800,7 +59061,7 @@ def test_common_project_path(): def test_parse_common_project_path(): expected = { - "project": "octopus", + "project": "abalone", } path = DataformClient.common_project_path(**expected) @@ -56810,8 +59071,8 @@ def test_parse_common_project_path(): def test_common_location_path(): - project = "oyster" - location = "nudibranch" + project = "squid" + location = "clam" expected = "projects/{project}/locations/{location}".format( project=project, location=location, @@ -56822,8 +59083,8 @@ def test_common_location_path(): def test_parse_common_location_path(): expected = { - "project": "cuttlefish", - "location": "mussel", + "project": "whelk", + "location": "octopus", } path = DataformClient.common_location_path(**expected) diff --git a/packages/google-cloud-dataproc/google/cloud/dataproc_v1/types/clusters.py b/packages/google-cloud-dataproc/google/cloud/dataproc_v1/types/clusters.py index a2e81a7ab472..8aff97ba7039 100644 --- a/packages/google-cloud-dataproc/google/cloud/dataproc_v1/types/clusters.py +++ b/packages/google-cloud-dataproc/google/cloud/dataproc_v1/types/clusters.py @@ -702,7 +702,12 @@ class GceClusterConfig(proto.Message): confidential_instance_config (google.cloud.dataproc_v1.types.ConfidentialInstanceConfig): Optional. Confidential Instance Config for clusters using `Confidential - VMs `__. + VMs `__. + resource_manager_tags (MutableMapping[str, str]): + Optional. [Resource manager tags] + (https://cloud.google.com/resource-manager/docs/tags/tags-creating-and-managing) + to add to all instances (see [Use secure tags] + (https://cloud.google.com/dataproc/docs/guides/use-secure-tags)). """ class PrivateIpv6GoogleAccess(proto.Enum): @@ -795,6 +800,11 @@ class PrivateIpv6GoogleAccess(proto.Enum): number=15, message="ConfidentialInstanceConfig", ) + resource_manager_tags: MutableMapping[str, str] = proto.MapField( + proto.STRING, + proto.STRING, + number=16, + ) class NodeGroupAffinity(proto.Message): @@ -866,18 +876,52 @@ class ShieldedInstanceConfig(proto.Message): class ConfidentialInstanceConfig(proto.Message): r"""Confidential Instance Config for clusters using `Confidential - VMs `__ + VMs `__ Attributes: enable_confidential_compute (bool): - Optional. Defines whether the instance should - have confidential compute enabled. + Optional. Deprecated: Use 'confidential_instance_type' + instead. Defines whether the instance should have + confidential compute enabled. + confidential_instance_type (google.cloud.dataproc_v1.types.ConfidentialInstanceConfig.ConfidentialInstanceType): + Optional. Defines the type of Confidential + Compute technology to use. """ + class ConfidentialInstanceType(proto.Enum): + r"""The type of Confidential Compute technology as per `Confidential + Computing + types `__. + New values may be added in the future. + + Values: + CONFIDENTIAL_INSTANCE_TYPE_UNSPECIFIED (0): + Confidential Instance Type is not specified. + SEV (1): + `AMD Secure Encrypted + Virtualization `__ + SEV_SNP (2): + `AMD Secure Encrypted Virtualization-Secure Nested + Paging `__ + TDX (3): + `Intel Trust Domain + Extensions `__ + """ + + CONFIDENTIAL_INSTANCE_TYPE_UNSPECIFIED = 0 + SEV = 1 + SEV_SNP = 2 + TDX = 3 + enable_confidential_compute: bool = proto.Field( proto.BOOL, number=1, ) + confidential_instance_type: ConfidentialInstanceType = proto.Field( + proto.ENUM, + number=2, + enum=ConfidentialInstanceType, + ) class InstanceGroupConfig(proto.Message): diff --git a/packages/google-cloud-dataproc/tests/unit/gapic/dataproc_v1/test_cluster_controller.py b/packages/google-cloud-dataproc/tests/unit/gapic/dataproc_v1/test_cluster_controller.py index c86e8b888fb4..026ebf0a39ed 100644 --- a/packages/google-cloud-dataproc/tests/unit/gapic/dataproc_v1/test_cluster_controller.py +++ b/packages/google-cloud-dataproc/tests/unit/gapic/dataproc_v1/test_cluster_controller.py @@ -6394,7 +6394,11 @@ def test_create_cluster_rest_call_success(request_type): "enable_vtpm": True, "enable_integrity_monitoring": True, }, - "confidential_instance_config": {"enable_confidential_compute": True}, + "confidential_instance_config": { + "enable_confidential_compute": True, + "confidential_instance_type": 1, + }, + "resource_manager_tags": {}, }, "master_config": { "num_instances": 1399, @@ -6814,7 +6818,11 @@ def test_update_cluster_rest_call_success(request_type): "enable_vtpm": True, "enable_integrity_monitoring": True, }, - "confidential_instance_config": {"enable_confidential_compute": True}, + "confidential_instance_config": { + "enable_confidential_compute": True, + "confidential_instance_type": 1, + }, + "resource_manager_tags": {}, }, "master_config": { "num_instances": 1399, diff --git a/packages/google-cloud-dataproc/tests/unit/gapic/dataproc_v1/test_workflow_template_service.py b/packages/google-cloud-dataproc/tests/unit/gapic/dataproc_v1/test_workflow_template_service.py index 11a8cfd67cd7..eba33660ce14 100644 --- a/packages/google-cloud-dataproc/tests/unit/gapic/dataproc_v1/test_workflow_template_service.py +++ b/packages/google-cloud-dataproc/tests/unit/gapic/dataproc_v1/test_workflow_template_service.py @@ -6030,8 +6030,10 @@ def test_create_workflow_template_rest_call_success(request_type): "enable_integrity_monitoring": True, }, "confidential_instance_config": { - "enable_confidential_compute": True + "enable_confidential_compute": True, + "confidential_instance_type": 1, }, + "resource_manager_tags": {}, }, "master_config": { "num_instances": 1399, @@ -6826,8 +6828,10 @@ def test_instantiate_inline_workflow_template_rest_call_success(request_type): "enable_integrity_monitoring": True, }, "confidential_instance_config": { - "enable_confidential_compute": True + "enable_confidential_compute": True, + "confidential_instance_type": 1, }, + "resource_manager_tags": {}, }, "master_config": { "num_instances": 1399, @@ -7340,8 +7344,10 @@ def test_update_workflow_template_rest_call_success(request_type): "enable_integrity_monitoring": True, }, "confidential_instance_config": { - "enable_confidential_compute": True + "enable_confidential_compute": True, + "confidential_instance_type": 1, }, + "resource_manager_tags": {}, }, "master_config": { "num_instances": 1399, diff --git a/packages/google-cloud-dialogflow-cx/google/cloud/dialogflowcx_v3/types/audio_config.py b/packages/google-cloud-dialogflow-cx/google/cloud/dialogflowcx_v3/types/audio_config.py index 4d5dfbd4f430..eb00038d3dea 100644 --- a/packages/google-cloud-dialogflow-cx/google/cloud/dialogflowcx_v3/types/audio_config.py +++ b/packages/google-cloud-dialogflow-cx/google/cloud/dialogflowcx_v3/types/audio_config.py @@ -180,7 +180,7 @@ class OutputAudioEncoding(proto.Enum): PCM). Audio content returned as LINEAR16 also contains a WAV header. LINT: LEGACY_NAMES OUTPUT_AUDIO_ENCODING_MP3 (2): - MP3 audio at 32kbps. + MP3 audio at 64kbps. OUTPUT_AUDIO_ENCODING_MP3_64_KBPS (4): MP3 audio at 64kbps. LINT: LEGACY_NAMES OUTPUT_AUDIO_ENCODING_OGG_OPUS (3): diff --git a/packages/google-cloud-dialogflow-cx/google/cloud/dialogflowcx_v3/types/session.py b/packages/google-cloud-dialogflow-cx/google/cloud/dialogflowcx_v3/types/session.py index a44003874b97..6f133f02b7be 100644 --- a/packages/google-cloud-dialogflow-cx/google/cloud/dialogflowcx_v3/types/session.py +++ b/packages/google-cloud-dialogflow-cx/google/cloud/dialogflowcx_v3/types/session.py @@ -89,6 +89,14 @@ class DetectIntentResponseView(proto.Enum): ----------------------------------------------- [QueryResult.diagnostic_info][google.cloud.dialogflow.cx.v3.QueryResult.diagnostic_info] + + - [QueryResult.generative_info][] + - + + [QueryResult.trace_blocks][google.cloud.dialogflow.cx.v3.QueryResult.trace_blocks] + ---------------------------------------------------------------------------------- + + [QueryResult.data_store_connection_signals][google.cloud.dialogflow.cx.v3.QueryResult.data_store_connection_signals] DETECT_INTENT_RESPONSE_VIEW_DEFAULT (3): Default response view omits the following fields: ------------------------------------------------- diff --git a/packages/google-cloud-dialogflow-cx/google/cloud/dialogflowcx_v3beta1/types/audio_config.py b/packages/google-cloud-dialogflow-cx/google/cloud/dialogflowcx_v3beta1/types/audio_config.py index 3fbeab092ae2..d661baaaec4e 100644 --- a/packages/google-cloud-dialogflow-cx/google/cloud/dialogflowcx_v3beta1/types/audio_config.py +++ b/packages/google-cloud-dialogflow-cx/google/cloud/dialogflowcx_v3beta1/types/audio_config.py @@ -181,7 +181,7 @@ class OutputAudioEncoding(proto.Enum): PCM). Audio content returned as LINEAR16 also contains a WAV header. LINT: LEGACY_NAMES OUTPUT_AUDIO_ENCODING_MP3 (2): - MP3 audio at 32kbps. + MP3 audio at 64kbps. OUTPUT_AUDIO_ENCODING_MP3_64_KBPS (4): MP3 audio at 64kbps. LINT: LEGACY_NAMES OUTPUT_AUDIO_ENCODING_OGG_OPUS (3): diff --git a/packages/google-cloud-dialogflow-cx/google/cloud/dialogflowcx_v3beta1/types/session.py b/packages/google-cloud-dialogflow-cx/google/cloud/dialogflowcx_v3beta1/types/session.py index 491400ec6cd8..7f2626baed6b 100644 --- a/packages/google-cloud-dialogflow-cx/google/cloud/dialogflowcx_v3beta1/types/session.py +++ b/packages/google-cloud-dialogflow-cx/google/cloud/dialogflowcx_v3beta1/types/session.py @@ -95,6 +95,12 @@ class DetectIntentResponseView(proto.Enum): --------------------------------------------------------------------------------------------- [QueryResult.generative_info][google.cloud.dialogflow.cx.v3beta1.QueryResult.generative_info] + --------------------------------------------------------------------------------------------- + + [QueryResult.trace_blocks][google.cloud.dialogflow.cx.v3beta1.QueryResult.trace_blocks] + --------------------------------------------------------------------------------------- + + [QueryResult.data_store_connection_signals][google.cloud.dialogflow.cx.v3beta1.QueryResult.data_store_connection_signals] DETECT_INTENT_RESPONSE_VIEW_DEFAULT (3): Default response view omits the following fields: ------------------------------------------------- diff --git a/packages/google-cloud-dialogflow/google/cloud/dialogflow/__init__.py b/packages/google-cloud-dialogflow/google/cloud/dialogflow/__init__.py index bdb578d75596..40ece2da8fa7 100644 --- a/packages/google-cloud-dialogflow/google/cloud/dialogflow/__init__.py +++ b/packages/google-cloud-dialogflow/google/cloud/dialogflow/__init__.py @@ -251,6 +251,7 @@ NotificationConfig, SetSuggestionFeatureConfigOperationMetadata, SetSuggestionFeatureConfigRequest, + SipConfig, SuggestionFeature, UpdateConversationProfileRequest, ) @@ -646,6 +647,7 @@ "NotificationConfig", "SetSuggestionFeatureConfigOperationMetadata", "SetSuggestionFeatureConfigRequest", + "SipConfig", "SuggestionFeature", "UpdateConversationProfileRequest", "CreateDocumentRequest", diff --git a/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2/__init__.py b/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2/__init__.py index 87ed765ed6cc..a41a2bc327c8 100644 --- a/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2/__init__.py +++ b/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2/__init__.py @@ -196,6 +196,7 @@ NotificationConfig, SetSuggestionFeatureConfigOperationMetadata, SetSuggestionFeatureConfigRequest, + SipConfig, SuggestionFeature, UpdateConversationProfileRequest, ) @@ -787,6 +788,7 @@ def _get_version(dependency_name): "SetAgentRequest", "SetSuggestionFeatureConfigOperationMetadata", "SetSuggestionFeatureConfigRequest", + "SipConfig", "SipTrunk", "SipTrunksClient", "SmartReplyAnswer", diff --git a/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2/services/participants/async_client.py b/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2/services/participants/async_client.py index 5357f1250f09..443202bb9a83 100644 --- a/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2/services/participants/async_client.py +++ b/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2/services/participants/async_client.py @@ -1083,8 +1083,14 @@ def request_generator(): 1. If the input was set to streaming audio, the first one or more messages contain recognition_result. Each recognition_result represents a more complete - transcript of what the user said. The last - recognition_result has is_final set to true. + transcript of what the user said. When a user + speaks multiple sentences, the API will emit + multiple messages where is_final = true. Each time + the system detects a distinct pause or completed + thought, it locks in that segment, marks it + is_final = true, and then immediately starts a new + recognition cycle for the next sentence on the + same stream. 2. In virtual agent stage: if enable_partial_automated_agent_reply is true, the diff --git a/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2/services/participants/client.py b/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2/services/participants/client.py index 40216fc5549c..41efcc61905b 100644 --- a/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2/services/participants/client.py +++ b/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2/services/participants/client.py @@ -1696,8 +1696,14 @@ def request_generator(): 1. If the input was set to streaming audio, the first one or more messages contain recognition_result. Each recognition_result represents a more complete - transcript of what the user said. The last - recognition_result has is_final set to true. + transcript of what the user said. When a user + speaks multiple sentences, the API will emit + multiple messages where is_final = true. Each time + the system detects a distinct pause or completed + thought, it locks in that segment, marks it + is_final = true, and then immediately starts a new + recognition cycle for the next sentence on the + same stream. 2. In virtual agent stage: if enable_partial_automated_agent_reply is true, the diff --git a/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2/types/__init__.py b/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2/types/__init__.py index 8ecbf73c0ec5..d8afdacb24cb 100644 --- a/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2/types/__init__.py +++ b/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2/types/__init__.py @@ -154,6 +154,7 @@ NotificationConfig, SetSuggestionFeatureConfigOperationMetadata, SetSuggestionFeatureConfigRequest, + SipConfig, SuggestionFeature, UpdateConversationProfileRequest, ) @@ -513,6 +514,7 @@ "NotificationConfig", "SetSuggestionFeatureConfigOperationMetadata", "SetSuggestionFeatureConfigRequest", + "SipConfig", "SuggestionFeature", "UpdateConversationProfileRequest", "CreateDocumentRequest", diff --git a/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2/types/audio_config.py b/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2/types/audio_config.py index c7561873924f..0e455b9dc087 100644 --- a/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2/types/audio_config.py +++ b/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2/types/audio_config.py @@ -253,7 +253,7 @@ class OutputAudioEncoding(proto.Enum): samples (Linear PCM). Audio content returned as LINEAR16 also contains a WAV header. OUTPUT_AUDIO_ENCODING_MP3 (2): - MP3 audio at 32kbps. + MP3 audio at 64kbps. OUTPUT_AUDIO_ENCODING_MP3_64_KBPS (4): MP3 audio at 64kbps. OUTPUT_AUDIO_ENCODING_OGG_OPUS (3): diff --git a/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2/types/ces_app.py b/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2/types/ces_app.py index cd0c38b5d7b8..7d49510c941b 100644 --- a/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2/types/ces_app.py +++ b/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2/types/ces_app.py @@ -32,6 +32,8 @@ class CesAppSpec(proto.Message): r"""Spec of CES app that the generator can choose from. + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: ces_app (str): Optional. Format: @@ -39,6 +41,20 @@ class CesAppSpec(proto.Message): confirmation_requirement (google.cloud.dialogflow_v2.types.Tool.ConfirmationRequirement): Optional. Indicates whether the app requires human confirmation. + proactive_enabled (bool): + Optional. Only applicable for CompanionAgent. Indicates + whether the ces app is enabled in proactive mode. At least + one of ``proactive_enabled`` or ``reactive_enabled`` should + be true; otherwise, the ces app will be ignored. + + This field is a member of `oneof`_ ``_proactive_enabled``. + reactive_enabled (bool): + Optional. Only applicable for CompanionAgent. Indicates + whether the ces app is enabled in reactive mode. At least + one of ``proactive_enabled`` or ``reactive_enabled`` should + be true; otherwise, the ces app will be ignored. + + This field is a member of `oneof`_ ``_reactive_enabled``. """ ces_app: str = proto.Field( @@ -50,6 +66,16 @@ class CesAppSpec(proto.Message): number=2, enum=tool.Tool.ConfirmationRequirement, ) + proactive_enabled: bool = proto.Field( + proto.BOOL, + number=3, + optional=True, + ) + reactive_enabled: bool = proto.Field( + proto.BOOL, + number=4, + optional=True, + ) __all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2/types/conversation.py b/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2/types/conversation.py index dc86d778d8e3..5be10d3de70f 100644 --- a/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2/types/conversation.py +++ b/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2/types/conversation.py @@ -1700,12 +1700,18 @@ class AnswerType(proto.Enum): The answer is from generative model. INTENT (3): The answer is from intent matching. + PLAYBOOK (4): + The answer is from Playbook. + EVENT (5): + The answer is from event. """ ANSWER_TYPE_UNSPECIFIED = 0 FAQ = 1 GENERATIVE = 2 INTENT = 3 + PLAYBOOK = 4 + EVENT = 5 class AnswerSource(proto.Message): r"""The sources of the answers. diff --git a/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2/types/conversation_profile.py b/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2/types/conversation_profile.py index a381b3dec71a..35cd96880a36 100644 --- a/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2/types/conversation_profile.py +++ b/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2/types/conversation_profile.py @@ -39,6 +39,7 @@ "HumanAgentHandoffConfig", "NotificationConfig", "LoggingConfig", + "SipConfig", "SuggestionFeature", "SetSuggestionFeatureConfigRequest", "ClearSuggestionFeatureConfigRequest", @@ -107,6 +108,8 @@ class ConversationProfile(proto.Message): languages. This should be a `BCP-47 `__ language tag. Example: "en-US". + sip_config (google.cloud.dialogflow_v2.types.SipConfig): + Optional. Configuration for SIP connections. time_zone (str): The time zone of this conversational profile from the `time zone database `__, e.g., @@ -187,6 +190,11 @@ class ConversationProfile(proto.Message): proto.STRING, number=10, ) + sip_config: "SipConfig" = proto.Field( + proto.MESSAGE, + number=16, + message="SipConfig", + ) time_zone: str = proto.Field( proto.STRING, number=14, @@ -472,6 +480,20 @@ class SuggestionFeatureConfig(proto.Message): rai_settings (google.cloud.dialogflow_v2.types.RaiSettings): Optional. Settings for Responsible AI checks. Supported features: KNOWLEDGE_ASSIST + suggestion_trigger_event (google.cloud.dialogflow_v2.types.TriggerEvent): + Optional. The trigger event for suggestion. If unspecified, + it will be ``CUSTOMER_MESSAGE``. Supported features: + KNOWLEDGE_ASSIST For KNOWLEDGE_ASSIST, these four trigger + events are supported: + + 1. TRIGGER_EVENT_UNSPECIFIED + 2. END_OF_UTTERANCE + 3. CUSTOMER_MESSAGE + 4. AGENT_MESSAGE + disable_query_search_context (bool): + Optional. If true, disable appending available search + context to the search query. Supported features: + KNOWLEDGE_ASSIST suggestion_trigger_settings (google.cloud.dialogflow_v2.types.HumanAgentAssistantConfig.SuggestionTriggerSettings): Settings of suggestion trigger. @@ -519,6 +541,15 @@ class SuggestionFeatureConfig(proto.Message): number=19, message=generator.RaiSettings, ) + suggestion_trigger_event: generator.TriggerEvent = proto.Field( + proto.ENUM, + number=20, + enum=generator.TriggerEvent, + ) + disable_query_search_context: bool = proto.Field( + proto.BOOL, + number=21, + ) suggestion_trigger_settings: "HumanAgentAssistantConfig.SuggestionTriggerSettings" = proto.Field( proto.MESSAGE, number=10, @@ -1215,6 +1246,67 @@ class LoggingConfig(proto.Message): ) +class SipConfig(proto.Message): + r"""Defines the SIP configuration. + + Attributes: + create_conversation_on_the_fly (bool): + Asks Dialogflow Telephony to create the + conversation provided in the SIP header on the + fly when the call comes in. + inactive_start (bool): + Starts the conversation with inactive SDP + directives + max_audio_recording_duration (google.protobuf.duration_pb2.Duration): + Max duration for audio recording. + Overrides the default value of 15 min. + Max value is 8 hours. + allow_virtual_agent_interaction (bool): + Allows interactions with a Dialogflow virtual + agent even if the call is connected for SIPREC + purposes. + keep_conversation_running (bool): + Keeps the conversation running even if the + call is disconnected. + copy_inbound_call_leg_headers (MutableSequence[str]): + List of inbound call leg headers to be copied + to outbound call legs created later. + ignore_reinvite_media_direction (bool): + Ignores any media direction in the reINVITE + SDP offer. Reuse the previous media direction. + """ + + create_conversation_on_the_fly: bool = proto.Field( + proto.BOOL, + number=1, + ) + inactive_start: bool = proto.Field( + proto.BOOL, + number=3, + ) + max_audio_recording_duration: duration_pb2.Duration = proto.Field( + proto.MESSAGE, + number=4, + message=duration_pb2.Duration, + ) + allow_virtual_agent_interaction: bool = proto.Field( + proto.BOOL, + number=5, + ) + keep_conversation_running: bool = proto.Field( + proto.BOOL, + number=6, + ) + copy_inbound_call_leg_headers: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=8, + ) + ignore_reinvite_media_direction: bool = proto.Field( + proto.BOOL, + number=9, + ) + + class SuggestionFeature(proto.Message): r"""The type of Human Agent Assistant API suggestion to perform, and the maximum number of results to return for that type. Multiple diff --git a/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2/types/participant.py b/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2/types/participant.py index 139aa5bfed9c..56f9fe9491fd 100644 --- a/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2/types/participant.py +++ b/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2/types/participant.py @@ -148,9 +148,9 @@ class Participant(proto.Message): participant. 2. If you set this field in - [AnalyzeContent][google.cloud.dialogflow.v2.AnalyzeContentRequest.participant] - or - [StreamingAnalyzeContent][google.cloud.dialogflow.v2.StreamingAnalyzeContentRequest.participant], + [AnalyzeContent][google.cloud.dialogflow.v2.AnalyzeContentRequest.obfuscated_external_user_id] + or [StreamingAnalyzeContent] + [google.cloud.dialogflow.v2.StreamingAnalyzeContentRequest.obfuscated_external_user_id], Dialogflow will update [Participant.obfuscated_external_user_id][google.cloud.dialogflow.v2.Participant.obfuscated_external_user_id]. @@ -163,6 +163,12 @@ class Participant(proto.Message): purposes. For example, Dialogflow determines whether a user in one conversation returned in a later conversation. + Additionally, to link an escalated Virtual Agent + conversation with its corresponding Agent Assist + conversation for analytics, this field in Agent Assist + conversations should be populated to indicate the user id of + the ``END_USER`` participant in the escalated conversation. + Note: - Please never pass raw user ids to Dialogflow. Always @@ -930,8 +936,12 @@ class StreamingAnalyzeContentResponse(proto.Message): 1. If the input was set to streaming audio, the first one or more messages contain ``recognition_result``. Each ``recognition_result`` represents a more complete transcript of - what the user said. The last ``recognition_result`` has - ``is_final`` set to ``true``. + what the user said. When a user speaks multiple sentences, the + API will emit multiple messages where ``is_final = true``. Each + time the system detects a distinct pause or completed thought, it + locks in that segment, marks it ``is_final = true``, and then + immediately starts a new recognition cycle for the next sentence + on the same stream. 2. In virtual agent stage: if ``enable_partial_automated_agent_reply`` is true, the following N @@ -2028,6 +2038,11 @@ class SuggestKnowledgeAssistResponse(proto.Message): [SuggestKnowledgeAssistRequest.context_size][google.cloud.dialogflow.v2.SuggestKnowledgeAssistRequest.context_size] field in the request if there are fewer messages in the conversation. + additional_suggested_query_results (MutableSequence[google.cloud.dialogflow_v2.types.KnowledgeAssistAnswer.AdditionalSuggestedQueryResult]): + Optional. The list of additional suggested + queries based on the context. This is used for + the cases when we want to generate multiple + queries for a single request. """ knowledge_assist_answer: "KnowledgeAssistAnswer" = proto.Field( @@ -2043,6 +2058,13 @@ class SuggestKnowledgeAssistResponse(proto.Message): proto.INT32, number=3, ) + additional_suggested_query_results: MutableSequence[ + "KnowledgeAssistAnswer.AdditionalSuggestedQueryResult" + ] = proto.RepeatedField( + proto.MESSAGE, + number=4, + message="KnowledgeAssistAnswer.AdditionalSuggestedQueryResult", + ) class IngestedContextReferenceDebugInfo(proto.Message): @@ -2205,6 +2227,10 @@ class KnowledgeAssistDebugInfo(proto.Message): search knowledge. service_latency (google.cloud.dialogflow_v2.types.ServiceLatency): The latency of the service. + query_generation_debug_info (google.cloud.dialogflow_v2.types.KnowledgeAssistDebugInfo.QueryGenerationDebugInfo): + Token usage metadata for query generation. + ces_debug_info (google.protobuf.struct_pb2.Struct): + Debug information from CES runtime API. """ class QueryGenerationFailureReason(proto.Enum): @@ -2411,6 +2437,33 @@ class KnowledgeAssistBehavior(proto.Message): number=18, ) + class QueryGenerationDebugInfo(proto.Message): + r"""Token usage metadata for query generation. + + Attributes: + prompt_token_count (int): + The total number of tokens in the prompt. + candidates_token_count (int): + The total number of tokens in the generated + candidates. + total_token_count (int): + The total number of tokens for the entire + request. + """ + + prompt_token_count: int = proto.Field( + proto.INT32, + number=1, + ) + candidates_token_count: int = proto.Field( + proto.INT32, + number=2, + ) + total_token_count: int = proto.Field( + proto.INT32, + number=3, + ) + query_generation_failure_reason: QueryGenerationFailureReason = proto.Field( proto.ENUM, number=1, @@ -2443,6 +2496,16 @@ class KnowledgeAssistBehavior(proto.Message): number=6, message="ServiceLatency", ) + query_generation_debug_info: QueryGenerationDebugInfo = proto.Field( + proto.MESSAGE, + number=7, + message=QueryGenerationDebugInfo, + ) + ces_debug_info: struct_pb2.Struct = proto.Field( + proto.MESSAGE, + number=8, + message=struct_pb2.Struct, + ) class KnowledgeAssistAnswer(proto.Message): @@ -2471,12 +2534,66 @@ class SuggestedQuery(proto.Message): Attributes: query_text (str): Suggested query text. + search_contexts (MutableSequence[google.cloud.dialogflow_v2.types.KnowledgeAssistAnswer.SuggestedQuery.SearchContext]): + Optional. The search contexts for the query. """ + class SearchContext(proto.Message): + r"""Search context is information useful for knowledge search that helps + enrich the query. Example: search_context { key: "application name" + value: "DesignApp" } + + Attributes: + key (str): + Optional. The key of the search context, e.g. + "application name". + value (str): + Optional. The value of the search context, + e.g. "DesignApp". + """ + + key: str = proto.Field( + proto.STRING, + number=1, + ) + value: str = proto.Field( + proto.STRING, + number=2, + ) + query_text: str = proto.Field( proto.STRING, number=1, ) + search_contexts: MutableSequence[ + "KnowledgeAssistAnswer.SuggestedQuery.SearchContext" + ] = proto.RepeatedField( + proto.MESSAGE, + number=4, + message="KnowledgeAssistAnswer.SuggestedQuery.SearchContext", + ) + + class AdditionalSuggestedQueryResult(proto.Message): + r"""Represents a single suggested query result. + + Attributes: + suggested_query (google.cloud.dialogflow_v2.types.KnowledgeAssistAnswer.SuggestedQuery): + Output only. The suggested query based on the + context. + answer_record (str): + Output only. The name of the answer record. Format: + ``projects//locations//answerRecords/`` + """ + + suggested_query: "KnowledgeAssistAnswer.SuggestedQuery" = proto.Field( + proto.MESSAGE, + number=1, + message="KnowledgeAssistAnswer.SuggestedQuery", + ) + answer_record: str = proto.Field( + proto.STRING, + number=5, + ) class KnowledgeAnswer(proto.Message): r"""Represents an answer from Knowledge. Currently supports FAQ @@ -2500,6 +2617,16 @@ class KnowledgeAnswer(proto.Message): generative_source (google.cloud.dialogflow_v2.types.KnowledgeAssistAnswer.KnowledgeAnswer.GenerativeSource): Populated if the prediction was Generative. + This field is a member of `oneof`_ ``source``. + playbook_source (google.cloud.dialogflow_v2.types.KnowledgeAssistAnswer.KnowledgeAnswer.GenerativeSource): + Populated if the prediction was from + Playbook. + + This field is a member of `oneof`_ ``source``. + event_source (google.cloud.dialogflow_v2.types.KnowledgeAssistAnswer.KnowledgeAnswer.EventSource): + Populated if the prediction was from an + event. + This field is a member of `oneof`_ ``source``. """ @@ -2565,6 +2692,28 @@ class Snippet(proto.Message): message="KnowledgeAssistAnswer.KnowledgeAnswer.GenerativeSource.Snippet", ) + class EventSource(proto.Message): + r"""Details about source of Event answer. + + Attributes: + event (str): + Name of the triggered event. + snippets (google.cloud.dialogflow_v2.types.KnowledgeAssistAnswer.KnowledgeAnswer.GenerativeSource): + Sources used in event fulfillment. + """ + + event: str = proto.Field( + proto.STRING, + number=1, + ) + snippets: "KnowledgeAssistAnswer.KnowledgeAnswer.GenerativeSource" = ( + proto.Field( + proto.MESSAGE, + number=2, + message="KnowledgeAssistAnswer.KnowledgeAnswer.GenerativeSource", + ) + ) + answer_text: str = proto.Field( proto.STRING, number=1, @@ -2583,6 +2732,20 @@ class Snippet(proto.Message): message="KnowledgeAssistAnswer.KnowledgeAnswer.GenerativeSource", ) ) + playbook_source: "KnowledgeAssistAnswer.KnowledgeAnswer.GenerativeSource" = ( + proto.Field( + proto.MESSAGE, + number=7, + oneof="source", + message="KnowledgeAssistAnswer.KnowledgeAnswer.GenerativeSource", + ) + ) + event_source: "KnowledgeAssistAnswer.KnowledgeAnswer.EventSource" = proto.Field( + proto.MESSAGE, + number=8, + oneof="source", + message="KnowledgeAssistAnswer.KnowledgeAnswer.EventSource", + ) suggested_query: SuggestedQuery = proto.Field( proto.MESSAGE, diff --git a/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2/types/session.py b/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2/types/session.py index 70a7f86252c7..eb576456d28c 100644 --- a/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2/types/session.py +++ b/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2/types/session.py @@ -953,20 +953,23 @@ class StreamingRecognitionResult(proto.Message): finalized transcript values received for the series of results. In the following example, single utterance is enabled. In the case - where single utterance is not enabled, result 7 would not occur. + where single utterance is not enabled, result 8 would not occur. :: - Num | transcript | message_type | is_final - --- | ----------------------- | ----------------------- | -------- - 1 | "tube" | TRANSCRIPT | false - 2 | "to be a" | TRANSCRIPT | false - 3 | "to be" | TRANSCRIPT | false - 4 | "to be or not to be" | TRANSCRIPT | true - 5 | "that's" | TRANSCRIPT | false - 6 | "that is | TRANSCRIPT | false - 7 | unset | END_OF_SINGLE_UTTERANCE | unset - 8 | " that is the question" | TRANSCRIPT | true + Num | transcript | message_type | is_final + --- | ------------------------ | ----------------------- | -------- + 1 | "tube" | TRANSCRIPT | false + 2 | "to be a" | TRANSCRIPT | false + 3 | "to be" | TRANSCRIPT | false + 4 | "to be or not to be" | TRANSCRIPT | true + 5 | "that's" | TRANSCRIPT | false + 6 | "that is | TRANSCRIPT | false + 7 | " that is the question" | TRANSCRIPT | true + 8 | unset | END_OF_SINGLE_UTTERANCE | unset + 9 | ". Whether 'tis nobler" | TRANSCRIPT | true + 10 | " in the mind" | TRANSCRIPT | false + 11 | " in the mind to suffer" | TRANSCRIPT | true Concatenating the finalized transcripts with ``is_final`` set to true, the complete utterance becomes "to be or not to be that is the diff --git a/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/__init__.py b/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/__init__.py index 348927177b65..677d45994ed6 100644 --- a/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/__init__.py +++ b/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/__init__.py @@ -155,6 +155,7 @@ NotificationConfig, SetSuggestionFeatureConfigOperationMetadata, SetSuggestionFeatureConfigRequest, + SipConfig, UpdateConversationProfileRequest, ) from .types.document import ( @@ -748,6 +749,7 @@ def _get_version(dependency_name): "SetAgentRequest", "SetSuggestionFeatureConfigOperationMetadata", "SetSuggestionFeatureConfigRequest", + "SipConfig", "SipTrunk", "SipTrunksClient", "SmartReplyAnswer", diff --git a/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/services/conversation_profiles/async_client.py b/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/services/conversation_profiles/async_client.py index 6f45169ecb37..3c42b86c7482 100644 --- a/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/services/conversation_profiles/async_client.py +++ b/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/services/conversation_profiles/async_client.py @@ -91,12 +91,6 @@ class ConversationProfilesAsyncClient: agent_path = staticmethod(ConversationProfilesClient.agent_path) parse_agent_path = staticmethod(ConversationProfilesClient.parse_agent_path) - conversation_model_path = staticmethod( - ConversationProfilesClient.conversation_model_path - ) - parse_conversation_model_path = staticmethod( - ConversationProfilesClient.parse_conversation_model_path - ) conversation_profile_path = staticmethod( ConversationProfilesClient.conversation_profile_path ) diff --git a/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/services/conversation_profiles/client.py b/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/services/conversation_profiles/client.py index 2d0559befcb4..19b1f5fd9781 100644 --- a/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/services/conversation_profiles/client.py +++ b/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/services/conversation_profiles/client.py @@ -257,28 +257,6 @@ def parse_agent_path(path: str) -> Dict[str, str]: m = re.match(r"^projects/(?P.+?)/agent$", path) return m.groupdict() if m else {} - @staticmethod - def conversation_model_path( - project: str, - location: str, - conversation_model: str, - ) -> str: - """Returns a fully-qualified conversation_model string.""" - return "projects/{project}/locations/{location}/conversationModels/{conversation_model}".format( - project=project, - location=location, - conversation_model=conversation_model, - ) - - @staticmethod - def parse_conversation_model_path(path: str) -> Dict[str, str]: - """Parses a conversation_model path into its component segments.""" - m = re.match( - r"^projects/(?P.+?)/locations/(?P.+?)/conversationModels/(?P.+?)$", - path, - ) - return m.groupdict() if m else {} - @staticmethod def conversation_profile_path( project: str, diff --git a/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/services/conversations/async_client.py b/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/services/conversations/async_client.py index 94b91994a310..1fda16f92477 100644 --- a/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/services/conversations/async_client.py +++ b/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/services/conversations/async_client.py @@ -97,10 +97,6 @@ class ConversationsAsyncClient: parse_ces_tool_path = staticmethod(ConversationsClient.parse_ces_tool_path) conversation_path = staticmethod(ConversationsClient.conversation_path) parse_conversation_path = staticmethod(ConversationsClient.parse_conversation_path) - conversation_model_path = staticmethod(ConversationsClient.conversation_model_path) - parse_conversation_model_path = staticmethod( - ConversationsClient.parse_conversation_model_path - ) conversation_profile_path = staticmethod( ConversationsClient.conversation_profile_path ) diff --git a/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/services/conversations/client.py b/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/services/conversations/client.py index 26338abd2790..b6afb1fb0531 100644 --- a/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/services/conversations/client.py +++ b/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/services/conversations/client.py @@ -337,28 +337,6 @@ def parse_conversation_path(path: str) -> Dict[str, str]: ) return m.groupdict() if m else {} - @staticmethod - def conversation_model_path( - project: str, - location: str, - conversation_model: str, - ) -> str: - """Returns a fully-qualified conversation_model string.""" - return "projects/{project}/locations/{location}/conversationModels/{conversation_model}".format( - project=project, - location=location, - conversation_model=conversation_model, - ) - - @staticmethod - def parse_conversation_model_path(path: str) -> Dict[str, str]: - """Parses a conversation_model path into its component segments.""" - m = re.match( - r"^projects/(?P.+?)/locations/(?P.+?)/conversationModels/(?P.+?)$", - path, - ) - return m.groupdict() if m else {} - @staticmethod def conversation_profile_path( project: str, diff --git a/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/services/participants/async_client.py b/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/services/participants/async_client.py index 487652cc40cd..2bc6844d9aab 100644 --- a/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/services/participants/async_client.py +++ b/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/services/participants/async_client.py @@ -1084,8 +1084,14 @@ def request_generator(): 1. If the input was set to streaming audio, the first one or more messages contain recognition_result. Each recognition_result represents a more complete - transcript of what the user said. The last - recognition_result has is_final set to true. + transcript of what the user said. When a user + speaks multiple sentences, the API will emit + multiple messages where is_final = true. Each time + the system detects a distinct pause or completed + thought, it locks in that segment, marks it + is_final = true, and then immediately starts a new + recognition cycle for the next sentence on the + same stream. 2. In virtual agent stage: if enable_partial_automated_agent_reply is true, the diff --git a/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/services/participants/client.py b/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/services/participants/client.py index 2f312a715d16..48932a52d078 100644 --- a/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/services/participants/client.py +++ b/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/services/participants/client.py @@ -1716,8 +1716,14 @@ def request_generator(): 1. If the input was set to streaming audio, the first one or more messages contain recognition_result. Each recognition_result represents a more complete - transcript of what the user said. The last - recognition_result has is_final set to true. + transcript of what the user said. When a user + speaks multiple sentences, the API will emit + multiple messages where is_final = true. Each time + the system detects a distinct pause or completed + thought, it locks in that segment, marks it + is_final = true, and then immediately starts a new + recognition cycle for the next sentence on the + same stream. 2. In virtual agent stage: if enable_partial_automated_agent_reply is true, the diff --git a/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/types/__init__.py b/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/types/__init__.py index 4f2e47e121b6..2ac08d2586ab 100644 --- a/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/types/__init__.py +++ b/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/types/__init__.py @@ -120,6 +120,7 @@ NotificationConfig, SetSuggestionFeatureConfigOperationMetadata, SetSuggestionFeatureConfigRequest, + SipConfig, UpdateConversationProfileRequest, ) from .document import ( @@ -468,6 +469,7 @@ "NotificationConfig", "SetSuggestionFeatureConfigOperationMetadata", "SetSuggestionFeatureConfigRequest", + "SipConfig", "UpdateConversationProfileRequest", "CreateDocumentRequest", "DeleteDocumentRequest", diff --git a/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/types/audio_config.py b/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/types/audio_config.py index 78b398238e49..84d54b30c9d1 100644 --- a/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/types/audio_config.py +++ b/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/types/audio_config.py @@ -256,7 +256,7 @@ class OutputAudioEncoding(proto.Enum): samples (Linear PCM). Audio content returned as LINEAR16 also contains a WAV header. OUTPUT_AUDIO_ENCODING_MP3 (2): - MP3 audio at 32kbps. + MP3 audio at 64kbps. OUTPUT_AUDIO_ENCODING_MP3_64_KBPS (4): MP3 audio at 64kbps. OUTPUT_AUDIO_ENCODING_OGG_OPUS (3): diff --git a/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/types/ces_app.py b/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/types/ces_app.py index a808025e9572..fcc18599e199 100644 --- a/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/types/ces_app.py +++ b/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/types/ces_app.py @@ -32,6 +32,8 @@ class CesAppSpec(proto.Message): r"""Spec of CES app that the generator can choose from. + .. _oneof: https://proto-plus-python.readthedocs.io/en/stable/fields.html#oneofs-mutually-exclusive-fields + Attributes: ces_app (str): Optional. Format: @@ -39,6 +41,20 @@ class CesAppSpec(proto.Message): confirmation_requirement (google.cloud.dialogflow_v2beta1.types.Tool.ConfirmationRequirement): Optional. Indicates whether the app requires human confirmation. + proactive_enabled (bool): + Optional. Only applicable for CompanionAgent. Indicates + whether the ces app is enabled in proactive mode. At least + one of ``proactive_enabled`` or ``reactive_enabled`` should + be true; otherwise, the ces app will be ignored. + + This field is a member of `oneof`_ ``_proactive_enabled``. + reactive_enabled (bool): + Optional. Only applicable for CompanionAgent. Indicates + whether the ces app is enabled in reactive mode. At least + one of ``proactive_enabled`` or ``reactive_enabled`` should + be true; otherwise, the ces app will be ignored. + + This field is a member of `oneof`_ ``_reactive_enabled``. """ ces_app: str = proto.Field( @@ -50,6 +66,16 @@ class CesAppSpec(proto.Message): number=2, enum=tool.Tool.ConfirmationRequirement, ) + proactive_enabled: bool = proto.Field( + proto.BOOL, + number=3, + optional=True, + ) + reactive_enabled: bool = proto.Field( + proto.BOOL, + number=4, + optional=True, + ) __all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/types/conversation.py b/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/types/conversation.py index 1829f5f34195..e55fbb023042 100644 --- a/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/types/conversation.py +++ b/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/types/conversation.py @@ -1771,12 +1771,18 @@ class AnswerType(proto.Enum): The answer is from generative model. INTENT (3): The answer is from intent matching. + PLAYBOOK (4): + The answer is from Playbook. + EVENT (5): + The answer is from event. """ ANSWER_TYPE_UNSPECIFIED = 0 FAQ = 1 GENERATIVE = 2 INTENT = 3 + PLAYBOOK = 4 + EVENT = 5 class AnswerSource(proto.Message): r"""The sources of the answers. diff --git a/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/types/conversation_profile.py b/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/types/conversation_profile.py index 86bc6437d975..582b2ff40abd 100644 --- a/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/types/conversation_profile.py +++ b/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/types/conversation_profile.py @@ -33,6 +33,7 @@ "HumanAgentHandoffConfig", "NotificationConfig", "LoggingConfig", + "SipConfig", "ListConversationProfilesRequest", "ListConversationProfilesResponse", "GetConversationProfileRequest", @@ -110,6 +111,8 @@ class ConversationProfile(proto.Message): languages. This should be a `BCP-47 `__ language tag. Example: "en-US". + sip_config (google.cloud.dialogflow_v2beta1.types.SipConfig): + Optional. Configuration for SIP connections. time_zone (str): The time zone of this conversational profile from the `time zone database `__, e.g., @@ -194,6 +197,11 @@ class ConversationProfile(proto.Message): proto.STRING, number=10, ) + sip_config: "SipConfig" = proto.Field( + proto.MESSAGE, + number=16, + message="SipConfig", + ) time_zone: str = proto.Field( proto.STRING, number=14, @@ -214,7 +222,8 @@ class AutomatedAgentConfig(proto.Message): Attributes: agent (str): - Required. ID of the Dialogflow agent environment to use. + Required. The resource name of the Dialogflow agent + environment to use. This project needs to either be the same project as the conversation or you need to grant @@ -335,6 +344,20 @@ class SuggestionFeatureConfig(proto.Message): rai_settings (google.cloud.dialogflow_v2beta1.types.RaiSettings): Optional. Settings for Responsible AI checks. Supported features: KNOWLEDGE_ASSIST + suggestion_trigger_event (google.cloud.dialogflow_v2beta1.types.TriggerEvent): + Optional. The trigger event for suggestion. If unspecified, + it will be ``CUSTOMER_MESSAGE``. Supported features: + KNOWLEDGE_ASSIST For KNOWLEDGE_ASSIST, these four trigger + events are supported: + + 1. TRIGGER_EVENT_UNSPECIFIED + 2. END_OF_UTTERANCE + 3. CUSTOMER_MESSAGE + 4. AGENT_MESSAGE + disable_query_search_context (bool): + Optional. If true, disable appending available search + context to the search query. Supported features: + KNOWLEDGE_ASSIST suggestion_trigger_settings (google.cloud.dialogflow_v2beta1.types.HumanAgentAssistantConfig.SuggestionTriggerSettings): Settings of suggestion trigger. @@ -342,8 +365,6 @@ class SuggestionFeatureConfig(proto.Message): DIALOGFLOW_ASSIST will use this field. query_config (google.cloud.dialogflow_v2beta1.types.HumanAgentAssistantConfig.SuggestionQueryConfig): Configs of query. - conversation_model_config (google.cloud.dialogflow_v2beta1.types.HumanAgentAssistantConfig.ConversationModelConfig): - Configs of custom conversation model. conversation_process_config (google.cloud.dialogflow_v2beta1.types.HumanAgentAssistantConfig.ConversationProcessConfig): Configs for processing conversation. """ @@ -382,6 +403,15 @@ class SuggestionFeatureConfig(proto.Message): number=19, message=generator.RaiSettings, ) + suggestion_trigger_event: generator.TriggerEvent = proto.Field( + proto.ENUM, + number=20, + enum=generator.TriggerEvent, + ) + disable_query_search_context: bool = proto.Field( + proto.BOOL, + number=21, + ) suggestion_trigger_settings: "HumanAgentAssistantConfig.SuggestionTriggerSettings" = proto.Field( proto.MESSAGE, number=10, @@ -392,11 +422,6 @@ class SuggestionFeatureConfig(proto.Message): number=6, message="HumanAgentAssistantConfig.SuggestionQueryConfig", ) - conversation_model_config: "HumanAgentAssistantConfig.ConversationModelConfig" = proto.Field( - proto.MESSAGE, - number=7, - message="HumanAgentAssistantConfig.ConversationModelConfig", - ) conversation_process_config: "HumanAgentAssistantConfig.ConversationProcessConfig" = proto.Field( proto.MESSAGE, number=8, @@ -769,40 +794,6 @@ class SectionType(proto.Enum): number=9, ) - class ConversationModelConfig(proto.Message): - r"""Custom conversation models used in agent assist feature. - - Supported feature: ARTICLE_SUGGESTION, SMART_COMPOSE, SMART_REPLY, - CONVERSATION_SUMMARIZATION. - - Attributes: - model (str): - Conversation model resource name. Format: - ``projects//conversationModels/``. - baseline_model_version (str): - Version of current baseline model. It will be ignored if - [model][google.cloud.dialogflow.v2beta1.HumanAgentAssistantConfig.ConversationModelConfig.model] - is set. Valid versions are: - - - Article Suggestion baseline model: - - - 0.9 - - 1.0 (default) - - - Summarization baseline model: - - - 1.0 - """ - - model: str = proto.Field( - proto.STRING, - number=1, - ) - baseline_model_version: str = proto.Field( - proto.STRING, - number=8, - ) - class ConversationProcessConfig(proto.Message): r"""Config to process conversation. @@ -1078,6 +1069,67 @@ class LoggingConfig(proto.Message): ) +class SipConfig(proto.Message): + r"""Defines the SIP configuration. + + Attributes: + create_conversation_on_the_fly (bool): + Asks Dialogflow Telephony to create the + conversation provided in the SIP header on the + fly when the call comes in. + inactive_start (bool): + Starts the conversation with inactive SDP + directives + max_audio_recording_duration (google.protobuf.duration_pb2.Duration): + Max duration for audio recording. + Overrides the default value of 15 min. + Max value is 8 hours. + allow_virtual_agent_interaction (bool): + Allows interactions with a Dialogflow virtual + agent even if the call is connected for SIPREC + purposes. + keep_conversation_running (bool): + Keeps the conversation running even if the + call is disconnected. + copy_inbound_call_leg_headers (MutableSequence[str]): + List of inbound call leg headers to be copied + to outbound call legs created later. + ignore_reinvite_media_direction (bool): + Ignores any media direction in the reINVITE + SDP offer. Reuse the previous media direction. + """ + + create_conversation_on_the_fly: bool = proto.Field( + proto.BOOL, + number=1, + ) + inactive_start: bool = proto.Field( + proto.BOOL, + number=3, + ) + max_audio_recording_duration: duration_pb2.Duration = proto.Field( + proto.MESSAGE, + number=4, + message=duration_pb2.Duration, + ) + allow_virtual_agent_interaction: bool = proto.Field( + proto.BOOL, + number=5, + ) + keep_conversation_running: bool = proto.Field( + proto.BOOL, + number=6, + ) + copy_inbound_call_leg_headers: MutableSequence[str] = proto.RepeatedField( + proto.STRING, + number=8, + ) + ignore_reinvite_media_direction: bool = proto.Field( + proto.BOOL, + number=9, + ) + + class ListConversationProfilesRequest(proto.Message): r"""The request message for [ConversationProfiles.ListConversationProfiles][google.cloud.dialogflow.v2beta1.ConversationProfiles.ListConversationProfiles]. diff --git a/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/types/participant.py b/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/types/participant.py index ae291df18bc9..f390755708ef 100644 --- a/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/types/participant.py +++ b/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/types/participant.py @@ -154,8 +154,8 @@ class Participant(proto.Message): 2. If you set this field in [AnalyzeContent][google.cloud.dialogflow.v2beta1.AnalyzeContentRequest.obfuscated_external_user_id] - or - [StreamingAnalyzeContent][google.cloud.dialogflow.v2beta1.StreamingAnalyzeContentRequest.obfuscated_external_user_id], + or [StreamingAnalyzeContent] + [google.cloud.dialogflow.v2beta1.StreamingAnalyzeContentRequest.obfuscated_external_user_id], Dialogflow will update [Participant.obfuscated_external_user_id][google.cloud.dialogflow.v2beta1.Participant.obfuscated_external_user_id]. @@ -169,6 +169,12 @@ class Participant(proto.Message): it to provide personalized smart reply suggestions for this user. + Additionally, to link an escalated Virtual Agent + conversation with its corresponding Agent Assist + conversation for analytics, this field in Agent Assist + conversations should be populated to indicate the user id of + the ``END_USER`` participant in the escalated conversation. + Note: - Please never pass raw user ids to Dialogflow. Always @@ -1443,8 +1449,12 @@ class StreamingAnalyzeContentResponse(proto.Message): 1. If the input was set to streaming audio, the first one or more messages contain ``recognition_result``. Each ``recognition_result`` represents a more complete transcript of - what the user said. The last ``recognition_result`` has - ``is_final`` set to ``true``. + what the user said. When a user speaks multiple sentences, the + API will emit multiple messages where ``is_final = true``. Each + time the system detects a distinct pause or completed thought, it + locks in that segment, marks it ``is_final = true``, and then + immediately starts a new recognition cycle for the next sentence + on the same stream. 2. In virtual agent stage: if ``enable_partial_automated_agent_reply`` is true, the following N @@ -2897,6 +2907,11 @@ class SuggestKnowledgeAssistResponse(proto.Message): [SuggestKnowledgeAssistRequest.context_size][google.cloud.dialogflow.v2beta1.SuggestKnowledgeAssistRequest.context_size] field in the request if there are fewer messages in the conversation. + additional_suggested_query_results (MutableSequence[google.cloud.dialogflow_v2beta1.types.KnowledgeAssistAnswer.AdditionalSuggestedQueryResult]): + Optional. The list of additional suggested + queries based on the context. This is used for + the cases when we want to generate multiple + queries for a single request. """ knowledge_assist_answer: "KnowledgeAssistAnswer" = proto.Field( @@ -2912,6 +2927,13 @@ class SuggestKnowledgeAssistResponse(proto.Message): proto.INT32, number=3, ) + additional_suggested_query_results: MutableSequence[ + "KnowledgeAssistAnswer.AdditionalSuggestedQueryResult" + ] = proto.RepeatedField( + proto.MESSAGE, + number=4, + message="KnowledgeAssistAnswer.AdditionalSuggestedQueryResult", + ) class IngestedContextReferenceDebugInfo(proto.Message): @@ -3074,6 +3096,10 @@ class KnowledgeAssistDebugInfo(proto.Message): search knowledge. service_latency (google.cloud.dialogflow_v2beta1.types.ServiceLatency): The latency of the service. + query_generation_debug_info (google.cloud.dialogflow_v2beta1.types.KnowledgeAssistDebugInfo.QueryGenerationDebugInfo): + Token usage metadata for query generation. + ces_debug_info (google.protobuf.struct_pb2.Struct): + Debug information from CES runtime API. """ class QueryGenerationFailureReason(proto.Enum): @@ -3280,6 +3306,33 @@ class KnowledgeAssistBehavior(proto.Message): number=18, ) + class QueryGenerationDebugInfo(proto.Message): + r"""Token usage metadata for query generation. + + Attributes: + prompt_token_count (int): + The total number of tokens in the prompt. + candidates_token_count (int): + The total number of tokens in the generated + candidates. + total_token_count (int): + The total number of tokens for the entire + request. + """ + + prompt_token_count: int = proto.Field( + proto.INT32, + number=1, + ) + candidates_token_count: int = proto.Field( + proto.INT32, + number=2, + ) + total_token_count: int = proto.Field( + proto.INT32, + number=3, + ) + query_generation_failure_reason: QueryGenerationFailureReason = proto.Field( proto.ENUM, number=1, @@ -3312,6 +3365,16 @@ class KnowledgeAssistBehavior(proto.Message): number=6, message="ServiceLatency", ) + query_generation_debug_info: QueryGenerationDebugInfo = proto.Field( + proto.MESSAGE, + number=7, + message=QueryGenerationDebugInfo, + ) + ces_debug_info: struct_pb2.Struct = proto.Field( + proto.MESSAGE, + number=8, + message=struct_pb2.Struct, + ) class KnowledgeAssistAnswer(proto.Message): @@ -3340,12 +3403,66 @@ class SuggestedQuery(proto.Message): Attributes: query_text (str): Suggested query text. + search_contexts (MutableSequence[google.cloud.dialogflow_v2beta1.types.KnowledgeAssistAnswer.SuggestedQuery.SearchContext]): + Optional. The search contexts for the query. """ + class SearchContext(proto.Message): + r"""Search context is information useful for knowledge search that helps + enrich the query. Example: search_context { key: "application name" + value: "DesignApp" } + + Attributes: + key (str): + Optional. The key of the search context, e.g. + "application name". + value (str): + Optional. The value of the search context, + e.g. "DesignApp". + """ + + key: str = proto.Field( + proto.STRING, + number=1, + ) + value: str = proto.Field( + proto.STRING, + number=2, + ) + query_text: str = proto.Field( proto.STRING, number=1, ) + search_contexts: MutableSequence[ + "KnowledgeAssistAnswer.SuggestedQuery.SearchContext" + ] = proto.RepeatedField( + proto.MESSAGE, + number=4, + message="KnowledgeAssistAnswer.SuggestedQuery.SearchContext", + ) + + class AdditionalSuggestedQueryResult(proto.Message): + r"""Represents a single suggested query result. + + Attributes: + suggested_query (google.cloud.dialogflow_v2beta1.types.KnowledgeAssistAnswer.SuggestedQuery): + Output only. The suggested query based on the + context. + answer_record (str): + Output only. The name of the answer record. Format: + ``projects//locations//answerRecords/`` + """ + + suggested_query: "KnowledgeAssistAnswer.SuggestedQuery" = proto.Field( + proto.MESSAGE, + number=1, + message="KnowledgeAssistAnswer.SuggestedQuery", + ) + answer_record: str = proto.Field( + proto.STRING, + number=5, + ) class KnowledgeAnswer(proto.Message): r"""Represents an answer from Knowledge. Currently supports FAQ @@ -3369,6 +3486,16 @@ class KnowledgeAnswer(proto.Message): generative_source (google.cloud.dialogflow_v2beta1.types.KnowledgeAssistAnswer.KnowledgeAnswer.GenerativeSource): Populated if the prediction was Generative. + This field is a member of `oneof`_ ``source``. + playbook_source (google.cloud.dialogflow_v2beta1.types.KnowledgeAssistAnswer.KnowledgeAnswer.GenerativeSource): + Populated if the prediction was from + Playbook. + + This field is a member of `oneof`_ ``source``. + event_source (google.cloud.dialogflow_v2beta1.types.KnowledgeAssistAnswer.KnowledgeAnswer.EventSource): + Populated if the prediction was from an + event. + This field is a member of `oneof`_ ``source``. """ @@ -3434,6 +3561,28 @@ class Snippet(proto.Message): message="KnowledgeAssistAnswer.KnowledgeAnswer.GenerativeSource.Snippet", ) + class EventSource(proto.Message): + r"""Details about source of Event answer. + + Attributes: + event (str): + Name of the triggered event. + snippets (google.cloud.dialogflow_v2beta1.types.KnowledgeAssistAnswer.KnowledgeAnswer.GenerativeSource): + Sources used in event fulfillment. + """ + + event: str = proto.Field( + proto.STRING, + number=1, + ) + snippets: "KnowledgeAssistAnswer.KnowledgeAnswer.GenerativeSource" = ( + proto.Field( + proto.MESSAGE, + number=2, + message="KnowledgeAssistAnswer.KnowledgeAnswer.GenerativeSource", + ) + ) + answer_text: str = proto.Field( proto.STRING, number=1, @@ -3452,6 +3601,20 @@ class Snippet(proto.Message): message="KnowledgeAssistAnswer.KnowledgeAnswer.GenerativeSource", ) ) + playbook_source: "KnowledgeAssistAnswer.KnowledgeAnswer.GenerativeSource" = ( + proto.Field( + proto.MESSAGE, + number=7, + oneof="source", + message="KnowledgeAssistAnswer.KnowledgeAnswer.GenerativeSource", + ) + ) + event_source: "KnowledgeAssistAnswer.KnowledgeAnswer.EventSource" = proto.Field( + proto.MESSAGE, + number=8, + oneof="source", + message="KnowledgeAssistAnswer.KnowledgeAnswer.EventSource", + ) suggested_query: SuggestedQuery = proto.Field( proto.MESSAGE, @@ -3622,8 +3785,55 @@ class TurnInput(proto.Message): virtual_agent_parameters (google.protobuf.struct_pb2.Struct): Optional. Parameters to be passed to the virtual agent. + tool_responses (google.cloud.dialogflow_v2beta1.types.BidiStreamingAnalyzeContentRequest.TurnInput.ToolResponses): + Optional. The tool responses from the client. """ + class ToolResponse(proto.Message): + r"""The execution result of a specific tool from the client. + + Attributes: + id (str): + Required. The matching ID of the tool call + the response is for. + tool (str): + Required. The identifier of the tool that got + executed. + response (google.protobuf.struct_pb2.Struct): + Optional. The tool execution result in JSON + object format. + """ + + id: str = proto.Field( + proto.STRING, + number=1, + ) + tool: str = proto.Field( + proto.STRING, + number=2, + ) + response: struct_pb2.Struct = proto.Field( + proto.MESSAGE, + number=3, + message=struct_pb2.Struct, + ) + + class ToolResponses(proto.Message): + r"""The tool responses from the client. + + Attributes: + tool_responses (MutableSequence[google.cloud.dialogflow_v2beta1.types.BidiStreamingAnalyzeContentRequest.TurnInput.ToolResponse]): + Optional. The list of tool responses. + """ + + tool_responses: MutableSequence[ + "BidiStreamingAnalyzeContentRequest.TurnInput.ToolResponse" + ] = proto.RepeatedField( + proto.MESSAGE, + number=1, + message="BidiStreamingAnalyzeContentRequest.TurnInput.ToolResponse", + ) + text: str = proto.Field( proto.STRING, number=1, @@ -3644,6 +3854,13 @@ class TurnInput(proto.Message): number=4, message=struct_pb2.Struct, ) + tool_responses: "BidiStreamingAnalyzeContentRequest.TurnInput.ToolResponses" = ( + proto.Field( + proto.MESSAGE, + number=5, + message="BidiStreamingAnalyzeContentRequest.TurnInput.ToolResponses", + ) + ) class Input(proto.Message): r"""Input for the conversation. @@ -3733,6 +3950,10 @@ class BidiStreamingAnalyzeContentResponse(proto.Message): turn_complete (google.cloud.dialogflow_v2beta1.types.BidiStreamingAnalyzeContentResponse.TurnComplete): Indicate that the turn is complete. + This field is a member of `oneof`_ ``response``. + tool_calls (google.cloud.dialogflow_v2beta1.types.BidiStreamingAnalyzeContentResponse.ToolCalls): + The tool calls from the server. + This field is a member of `oneof`_ ``response``. """ @@ -3742,6 +3963,49 @@ class BargeInSignal(proto.Message): class TurnComplete(proto.Message): r"""Indicate that the turn is complete.""" + class ToolCall(proto.Message): + r"""Request for the client to execute the specified tool. + + Attributes: + id (str): + The unique identifier of the tool call. + tool (str): + The identifier of the tool to execute. + args (google.protobuf.struct_pb2.Struct): + The input parameters and values for the tool + in JSON object format. + """ + + id: str = proto.Field( + proto.STRING, + number=1, + ) + tool: str = proto.Field( + proto.STRING, + number=2, + ) + args: struct_pb2.Struct = proto.Field( + proto.MESSAGE, + number=3, + message=struct_pb2.Struct, + ) + + class ToolCalls(proto.Message): + r"""The tool calls from the server. + + Attributes: + tool_calls (MutableSequence[google.cloud.dialogflow_v2beta1.types.BidiStreamingAnalyzeContentResponse.ToolCall]): + The list of tool calls. + """ + + tool_calls: MutableSequence["BidiStreamingAnalyzeContentResponse.ToolCall"] = ( + proto.RepeatedField( + proto.MESSAGE, + number=1, + message="BidiStreamingAnalyzeContentResponse.ToolCall", + ) + ) + recognition_result: session.StreamingRecognitionResult = proto.Field( proto.MESSAGE, number=1, @@ -3766,6 +4030,12 @@ class TurnComplete(proto.Message): oneof="response", message=TurnComplete, ) + tool_calls: ToolCalls = proto.Field( + proto.MESSAGE, + number=5, + oneof="response", + message=ToolCalls, + ) __all__ = tuple(sorted(__protobuf__.manifest)) diff --git a/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/types/session.py b/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/types/session.py index bc8249911dec..f70d908473bd 100644 --- a/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/types/session.py +++ b/packages/google-cloud-dialogflow/google/cloud/dialogflow_v2beta1/types/session.py @@ -1133,20 +1133,23 @@ class StreamingRecognitionResult(proto.Message): finalized transcript values received for the series of results. In the following example, single utterance is enabled. In the case - where single utterance is not enabled, result 7 would not occur. + where single utterance is not enabled, result 8 would not occur. :: - Num | transcript | message_type | is_final - --- | ----------------------- | ----------------------- | -------- - 1 | "tube" | TRANSCRIPT | false - 2 | "to be a" | TRANSCRIPT | false - 3 | "to be" | TRANSCRIPT | false - 4 | "to be or not to be" | TRANSCRIPT | true - 5 | "that's" | TRANSCRIPT | false - 6 | "that is | TRANSCRIPT | false - 7 | unset | END_OF_SINGLE_UTTERANCE | unset - 8 | " that is the question" | TRANSCRIPT | true + Num | transcript | message_type | is_final + --- | ------------------------ | ----------------------- | -------- + 1 | "tube" | TRANSCRIPT | false + 2 | "to be a" | TRANSCRIPT | false + 3 | "to be" | TRANSCRIPT | false + 4 | "to be or not to be" | TRANSCRIPT | true + 5 | "that's" | TRANSCRIPT | false + 6 | "that is | TRANSCRIPT | false + 7 | " that is the question" | TRANSCRIPT | true + 8 | unset | END_OF_SINGLE_UTTERANCE | unset + 9 | ". Whether 'tis nobler" | TRANSCRIPT | true + 10 | " in the mind" | TRANSCRIPT | false + 11 | " in the mind to suffer" | TRANSCRIPT | true Concatenating the finalized transcripts with ``is_final`` set to true, the complete utterance becomes "to be or not to be that is the diff --git a/packages/google-cloud-dialogflow/tests/unit/gapic/dialogflow_v2/test_conversation_profiles.py b/packages/google-cloud-dialogflow/tests/unit/gapic/dialogflow_v2/test_conversation_profiles.py index 8fcb9d5ff37e..84ce6f6f8f40 100644 --- a/packages/google-cloud-dialogflow/tests/unit/gapic/dialogflow_v2/test_conversation_profiles.py +++ b/packages/google-cloud-dialogflow/tests/unit/gapic/dialogflow_v2/test_conversation_profiles.py @@ -6427,6 +6427,8 @@ def test_create_conversation_profile_rest_call_success(request_type): {"category": 1, "sensitivity_level": 1} ] }, + "suggestion_trigger_event": 1, + "disable_query_search_context": True, "suggestion_trigger_settings": { "no_smalltalk": True, "only_end_user": True, @@ -6500,6 +6502,18 @@ def test_create_conversation_profile_rest_call_success(request_type): "use_timeout_based_endpointing": True, }, "language_code": "language_code_value", + "sip_config": { + "create_conversation_on_the_fly": True, + "inactive_start": True, + "max_audio_recording_duration": {}, + "allow_virtual_agent_interaction": True, + "keep_conversation_running": True, + "copy_inbound_call_leg_headers": [ + "copy_inbound_call_leg_headers_value1", + "copy_inbound_call_leg_headers_value2", + ], + "ignore_reinvite_media_direction": True, + }, "time_zone": "time_zone_value", "security_settings": "security_settings_value", "tts_config": { @@ -6771,6 +6785,8 @@ def test_update_conversation_profile_rest_call_success(request_type): {"category": 1, "sensitivity_level": 1} ] }, + "suggestion_trigger_event": 1, + "disable_query_search_context": True, "suggestion_trigger_settings": { "no_smalltalk": True, "only_end_user": True, @@ -6844,6 +6860,18 @@ def test_update_conversation_profile_rest_call_success(request_type): "use_timeout_based_endpointing": True, }, "language_code": "language_code_value", + "sip_config": { + "create_conversation_on_the_fly": True, + "inactive_start": True, + "max_audio_recording_duration": {}, + "allow_virtual_agent_interaction": True, + "keep_conversation_running": True, + "copy_inbound_call_leg_headers": [ + "copy_inbound_call_leg_headers_value1", + "copy_inbound_call_leg_headers_value2", + ], + "ignore_reinvite_media_direction": True, + }, "time_zone": "time_zone_value", "security_settings": "security_settings_value", "tts_config": { diff --git a/packages/google-cloud-dialogflow/tests/unit/gapic/dialogflow_v2/test_conversations.py b/packages/google-cloud-dialogflow/tests/unit/gapic/dialogflow_v2/test_conversations.py index b310d6344eec..92a163cf1646 100644 --- a/packages/google-cloud-dialogflow/tests/unit/gapic/dialogflow_v2/test_conversations.py +++ b/packages/google-cloud-dialogflow/tests/unit/gapic/dialogflow_v2/test_conversations.py @@ -8173,6 +8173,8 @@ def test_create_conversation_rest_call_success(request_type): {"category": 1, "sensitivity_level": 1} ] }, + "suggestion_trigger_event": 1, + "disable_query_search_context": True, "suggestion_trigger_settings": { "no_smalltalk": True, "only_end_user": True, @@ -8251,6 +8253,18 @@ def test_create_conversation_rest_call_success(request_type): "use_timeout_based_endpointing": True, }, "language_code": "language_code_value", + "sip_config": { + "create_conversation_on_the_fly": True, + "inactive_start": True, + "max_audio_recording_duration": {}, + "allow_virtual_agent_interaction": True, + "keep_conversation_running": True, + "copy_inbound_call_leg_headers": [ + "copy_inbound_call_leg_headers_value1", + "copy_inbound_call_leg_headers_value2", + ], + "ignore_reinvite_media_direction": True, + }, "time_zone": "time_zone_value", "security_settings": "security_settings_value", "tts_config": { diff --git a/packages/google-cloud-dialogflow/tests/unit/gapic/dialogflow_v2/test_generator_evaluations.py b/packages/google-cloud-dialogflow/tests/unit/gapic/dialogflow_v2/test_generator_evaluations.py index 7acad967389f..34f5193451c2 100644 --- a/packages/google-cloud-dialogflow/tests/unit/gapic/dialogflow_v2/test_generator_evaluations.py +++ b/packages/google-cloud-dialogflow/tests/unit/gapic/dialogflow_v2/test_generator_evaluations.py @@ -4387,7 +4387,12 @@ def test_create_generator_evaluation_rest_call_success(request_type): {"ces_tool": "ces_tool_value", "confirmation_requirement": 1} ], "ces_app_specs": [ - {"ces_app": "ces_app_value", "confirmation_requirement": 1} + { + "ces_app": "ces_app_value", + "confirmation_requirement": 1, + "proactive_enabled": True, + "reactive_enabled": True, + } ], }, "summarization_metrics": { diff --git a/packages/google-cloud-dialogflow/tests/unit/gapic/dialogflow_v2/test_generators.py b/packages/google-cloud-dialogflow/tests/unit/gapic/dialogflow_v2/test_generators.py index cea141ce8c18..16f56aa5c772 100644 --- a/packages/google-cloud-dialogflow/tests/unit/gapic/dialogflow_v2/test_generators.py +++ b/packages/google-cloud-dialogflow/tests/unit/gapic/dialogflow_v2/test_generators.py @@ -4692,7 +4692,14 @@ def test_create_generator_rest_call_success(request_type): "ces_tool_specs": [ {"ces_tool": "ces_tool_value", "confirmation_requirement": 1} ], - "ces_app_specs": [{"ces_app": "ces_app_value", "confirmation_requirement": 1}], + "ces_app_specs": [ + { + "ces_app": "ces_app_value", + "confirmation_requirement": 1, + "proactive_enabled": True, + "reactive_enabled": True, + } + ], } # The version of a generated dependency at test runtime may differ from the version used during generation. # Delete any fields which are not present in the current runtime dependency @@ -5414,7 +5421,14 @@ def test_update_generator_rest_call_success(request_type): "ces_tool_specs": [ {"ces_tool": "ces_tool_value", "confirmation_requirement": 1} ], - "ces_app_specs": [{"ces_app": "ces_app_value", "confirmation_requirement": 1}], + "ces_app_specs": [ + { + "ces_app": "ces_app_value", + "confirmation_requirement": 1, + "proactive_enabled": True, + "reactive_enabled": True, + } + ], } # The version of a generated dependency at test runtime may differ from the version used during generation. # Delete any fields which are not present in the current runtime dependency diff --git a/packages/google-cloud-dialogflow/tests/unit/gapic/dialogflow_v2beta1/test_conversation_profiles.py b/packages/google-cloud-dialogflow/tests/unit/gapic/dialogflow_v2beta1/test_conversation_profiles.py index b29df5e84d29..3ede2db70088 100644 --- a/packages/google-cloud-dialogflow/tests/unit/gapic/dialogflow_v2beta1/test_conversation_profiles.py +++ b/packages/google-cloud-dialogflow/tests/unit/gapic/dialogflow_v2beta1/test_conversation_profiles.py @@ -6453,6 +6453,8 @@ def test_create_conversation_profile_rest_call_success(request_type): {"category": 1, "sensitivity_level": 1} ] }, + "suggestion_trigger_event": 1, + "disable_query_search_context": True, "suggestion_trigger_settings": { "no_small_talk": True, "only_end_user": True, @@ -6481,10 +6483,6 @@ def test_create_conversation_profile_rest_call_success(request_type): "sections": {"section_types": [1]}, "context_size": 1311, }, - "conversation_model_config": { - "model": "model_value", - "baseline_model_version": "baseline_model_version_value", - }, "conversation_process_config": {"recent_sentences_count": 2352}, } ], @@ -6526,6 +6524,18 @@ def test_create_conversation_profile_rest_call_success(request_type): "use_timeout_based_endpointing": True, }, "language_code": "language_code_value", + "sip_config": { + "create_conversation_on_the_fly": True, + "inactive_start": True, + "max_audio_recording_duration": {}, + "allow_virtual_agent_interaction": True, + "keep_conversation_running": True, + "copy_inbound_call_leg_headers": [ + "copy_inbound_call_leg_headers_value1", + "copy_inbound_call_leg_headers_value2", + ], + "ignore_reinvite_media_direction": True, + }, "time_zone": "time_zone_value", "security_settings": "security_settings_value", "tts_config": { @@ -6800,6 +6810,8 @@ def test_update_conversation_profile_rest_call_success(request_type): {"category": 1, "sensitivity_level": 1} ] }, + "suggestion_trigger_event": 1, + "disable_query_search_context": True, "suggestion_trigger_settings": { "no_small_talk": True, "only_end_user": True, @@ -6828,10 +6840,6 @@ def test_update_conversation_profile_rest_call_success(request_type): "sections": {"section_types": [1]}, "context_size": 1311, }, - "conversation_model_config": { - "model": "model_value", - "baseline_model_version": "baseline_model_version_value", - }, "conversation_process_config": {"recent_sentences_count": 2352}, } ], @@ -6873,6 +6881,18 @@ def test_update_conversation_profile_rest_call_success(request_type): "use_timeout_based_endpointing": True, }, "language_code": "language_code_value", + "sip_config": { + "create_conversation_on_the_fly": True, + "inactive_start": True, + "max_audio_recording_duration": {}, + "allow_virtual_agent_interaction": True, + "keep_conversation_running": True, + "copy_inbound_call_leg_headers": [ + "copy_inbound_call_leg_headers_value1", + "copy_inbound_call_leg_headers_value2", + ], + "ignore_reinvite_media_direction": True, + }, "time_zone": "time_zone_value", "security_settings": "security_settings_value", "tts_config": { @@ -8460,37 +8480,9 @@ def test_parse_agent_path(): assert expected == actual -def test_conversation_model_path(): - project = "whelk" - location = "octopus" - conversation_model = "oyster" - expected = "projects/{project}/locations/{location}/conversationModels/{conversation_model}".format( - project=project, - location=location, - conversation_model=conversation_model, - ) - actual = ConversationProfilesClient.conversation_model_path( - project, location, conversation_model - ) - assert expected == actual - - -def test_parse_conversation_model_path(): - expected = { - "project": "nudibranch", - "location": "cuttlefish", - "conversation_model": "mussel", - } - path = ConversationProfilesClient.conversation_model_path(**expected) - - # Check that the path construction is reversible. - actual = ConversationProfilesClient.parse_conversation_model_path(path) - assert expected == actual - - def test_conversation_profile_path(): - project = "winkle" - conversation_profile = "nautilus" + project = "whelk" + conversation_profile = "octopus" expected = "projects/{project}/conversationProfiles/{conversation_profile}".format( project=project, conversation_profile=conversation_profile, @@ -8503,8 +8495,8 @@ def test_conversation_profile_path(): def test_parse_conversation_profile_path(): expected = { - "project": "scallop", - "conversation_profile": "abalone", + "project": "oyster", + "conversation_profile": "nudibranch", } path = ConversationProfilesClient.conversation_profile_path(**expected) @@ -8514,9 +8506,9 @@ def test_parse_conversation_profile_path(): def test_cx_security_settings_path(): - project = "squid" - location = "clam" - security_settings = "whelk" + project = "cuttlefish" + location = "mussel" + security_settings = "winkle" expected = "projects/{project}/locations/{location}/securitySettings/{security_settings}".format( project=project, location=location, @@ -8530,9 +8522,9 @@ def test_cx_security_settings_path(): def test_parse_cx_security_settings_path(): expected = { - "project": "octopus", - "location": "oyster", - "security_settings": "nudibranch", + "project": "nautilus", + "location": "scallop", + "security_settings": "abalone", } path = ConversationProfilesClient.cx_security_settings_path(**expected) @@ -8542,9 +8534,9 @@ def test_parse_cx_security_settings_path(): def test_document_path(): - project = "cuttlefish" - knowledge_base = "mussel" - document = "winkle" + project = "squid" + knowledge_base = "clam" + document = "whelk" expected = "projects/{project}/knowledgeBases/{knowledge_base}/documents/{document}".format( project=project, knowledge_base=knowledge_base, @@ -8556,9 +8548,9 @@ def test_document_path(): def test_parse_document_path(): expected = { - "project": "nautilus", - "knowledge_base": "scallop", - "document": "abalone", + "project": "octopus", + "knowledge_base": "oyster", + "document": "nudibranch", } path = ConversationProfilesClient.document_path(**expected) @@ -8568,9 +8560,9 @@ def test_parse_document_path(): def test_generator_path(): - project = "squid" - location = "clam" - generator = "whelk" + project = "cuttlefish" + location = "mussel" + generator = "winkle" expected = "projects/{project}/locations/{location}/generators/{generator}".format( project=project, location=location, @@ -8582,9 +8574,9 @@ def test_generator_path(): def test_parse_generator_path(): expected = { - "project": "octopus", - "location": "oyster", - "generator": "nudibranch", + "project": "nautilus", + "location": "scallop", + "generator": "abalone", } path = ConversationProfilesClient.generator_path(**expected) @@ -8594,8 +8586,8 @@ def test_parse_generator_path(): def test_knowledge_base_path(): - project = "cuttlefish" - knowledge_base = "mussel" + project = "squid" + knowledge_base = "clam" expected = "projects/{project}/knowledgeBases/{knowledge_base}".format( project=project, knowledge_base=knowledge_base, @@ -8606,8 +8598,8 @@ def test_knowledge_base_path(): def test_parse_knowledge_base_path(): expected = { - "project": "winkle", - "knowledge_base": "nautilus", + "project": "whelk", + "knowledge_base": "octopus", } path = ConversationProfilesClient.knowledge_base_path(**expected) @@ -8617,9 +8609,9 @@ def test_parse_knowledge_base_path(): def test_phrase_set_path(): - project = "scallop" - location = "abalone" - phrase_set = "squid" + project = "oyster" + location = "nudibranch" + phrase_set = "cuttlefish" expected = "projects/{project}/locations/{location}/phraseSets/{phrase_set}".format( project=project, location=location, @@ -8631,9 +8623,9 @@ def test_phrase_set_path(): def test_parse_phrase_set_path(): expected = { - "project": "clam", - "location": "whelk", - "phrase_set": "octopus", + "project": "mussel", + "location": "winkle", + "phrase_set": "nautilus", } path = ConversationProfilesClient.phrase_set_path(**expected) @@ -8643,7 +8635,7 @@ def test_parse_phrase_set_path(): def test_common_billing_account_path(): - billing_account = "oyster" + billing_account = "scallop" expected = "billingAccounts/{billing_account}".format( billing_account=billing_account, ) @@ -8653,7 +8645,7 @@ def test_common_billing_account_path(): def test_parse_common_billing_account_path(): expected = { - "billing_account": "nudibranch", + "billing_account": "abalone", } path = ConversationProfilesClient.common_billing_account_path(**expected) @@ -8663,7 +8655,7 @@ def test_parse_common_billing_account_path(): def test_common_folder_path(): - folder = "cuttlefish" + folder = "squid" expected = "folders/{folder}".format( folder=folder, ) @@ -8673,7 +8665,7 @@ def test_common_folder_path(): def test_parse_common_folder_path(): expected = { - "folder": "mussel", + "folder": "clam", } path = ConversationProfilesClient.common_folder_path(**expected) @@ -8683,7 +8675,7 @@ def test_parse_common_folder_path(): def test_common_organization_path(): - organization = "winkle" + organization = "whelk" expected = "organizations/{organization}".format( organization=organization, ) @@ -8693,7 +8685,7 @@ def test_common_organization_path(): def test_parse_common_organization_path(): expected = { - "organization": "nautilus", + "organization": "octopus", } path = ConversationProfilesClient.common_organization_path(**expected) @@ -8703,7 +8695,7 @@ def test_parse_common_organization_path(): def test_common_project_path(): - project = "scallop" + project = "oyster" expected = "projects/{project}".format( project=project, ) @@ -8713,7 +8705,7 @@ def test_common_project_path(): def test_parse_common_project_path(): expected = { - "project": "abalone", + "project": "nudibranch", } path = ConversationProfilesClient.common_project_path(**expected) @@ -8723,8 +8715,8 @@ def test_parse_common_project_path(): def test_common_location_path(): - project = "squid" - location = "clam" + project = "cuttlefish" + location = "mussel" expected = "projects/{project}/locations/{location}".format( project=project, location=location, @@ -8735,8 +8727,8 @@ def test_common_location_path(): def test_parse_common_location_path(): expected = { - "project": "whelk", - "location": "octopus", + "project": "winkle", + "location": "nautilus", } path = ConversationProfilesClient.common_location_path(**expected) diff --git a/packages/google-cloud-dialogflow/tests/unit/gapic/dialogflow_v2beta1/test_conversations.py b/packages/google-cloud-dialogflow/tests/unit/gapic/dialogflow_v2beta1/test_conversations.py index ffb3f09588bb..c5ac9023248c 100644 --- a/packages/google-cloud-dialogflow/tests/unit/gapic/dialogflow_v2beta1/test_conversations.py +++ b/packages/google-cloud-dialogflow/tests/unit/gapic/dialogflow_v2beta1/test_conversations.py @@ -8769,6 +8769,8 @@ def test_create_conversation_rest_call_success(request_type): {"category": 1, "sensitivity_level": 1} ] }, + "suggestion_trigger_event": 1, + "disable_query_search_context": True, "suggestion_trigger_settings": { "no_small_talk": True, "only_end_user": True, @@ -8800,10 +8802,6 @@ def test_create_conversation_rest_call_success(request_type): "sections": {"section_types": [1]}, "context_size": 1311, }, - "conversation_model_config": { - "model": "model_value", - "baseline_model_version": "baseline_model_version_value", - }, "conversation_process_config": { "recent_sentences_count": 2352 }, @@ -8847,6 +8845,18 @@ def test_create_conversation_rest_call_success(request_type): "use_timeout_based_endpointing": True, }, "language_code": "language_code_value", + "sip_config": { + "create_conversation_on_the_fly": True, + "inactive_start": True, + "max_audio_recording_duration": {}, + "allow_virtual_agent_interaction": True, + "keep_conversation_running": True, + "copy_inbound_call_leg_headers": [ + "copy_inbound_call_leg_headers_value1", + "copy_inbound_call_leg_headers_value2", + ], + "ignore_reinvite_media_direction": True, + }, "time_zone": "time_zone_value", "security_settings": "security_settings_value", "tts_config": { @@ -11719,37 +11729,9 @@ def test_parse_conversation_path(): assert expected == actual -def test_conversation_model_path(): - project = "squid" - location = "clam" - conversation_model = "whelk" - expected = "projects/{project}/locations/{location}/conversationModels/{conversation_model}".format( - project=project, - location=location, - conversation_model=conversation_model, - ) - actual = ConversationsClient.conversation_model_path( - project, location, conversation_model - ) - assert expected == actual - - -def test_parse_conversation_model_path(): - expected = { - "project": "octopus", - "location": "oyster", - "conversation_model": "nudibranch", - } - path = ConversationsClient.conversation_model_path(**expected) - - # Check that the path construction is reversible. - actual = ConversationsClient.parse_conversation_model_path(path) - assert expected == actual - - def test_conversation_profile_path(): - project = "cuttlefish" - conversation_profile = "mussel" + project = "squid" + conversation_profile = "clam" expected = "projects/{project}/conversationProfiles/{conversation_profile}".format( project=project, conversation_profile=conversation_profile, @@ -11762,8 +11744,8 @@ def test_conversation_profile_path(): def test_parse_conversation_profile_path(): expected = { - "project": "winkle", - "conversation_profile": "nautilus", + "project": "whelk", + "conversation_profile": "octopus", } path = ConversationsClient.conversation_profile_path(**expected) @@ -11773,9 +11755,9 @@ def test_parse_conversation_profile_path(): def test_cx_security_settings_path(): - project = "scallop" - location = "abalone" - security_settings = "squid" + project = "oyster" + location = "nudibranch" + security_settings = "cuttlefish" expected = "projects/{project}/locations/{location}/securitySettings/{security_settings}".format( project=project, location=location, @@ -11789,9 +11771,9 @@ def test_cx_security_settings_path(): def test_parse_cx_security_settings_path(): expected = { - "project": "clam", - "location": "whelk", - "security_settings": "octopus", + "project": "mussel", + "location": "winkle", + "security_settings": "nautilus", } path = ConversationsClient.cx_security_settings_path(**expected) @@ -11801,10 +11783,10 @@ def test_parse_cx_security_settings_path(): def test_data_store_path(): - project = "oyster" - location = "nudibranch" - collection = "cuttlefish" - data_store = "mussel" + project = "scallop" + location = "abalone" + collection = "squid" + data_store = "clam" expected = "projects/{project}/locations/{location}/collections/{collection}/dataStores/{data_store}".format( project=project, location=location, @@ -11819,10 +11801,10 @@ def test_data_store_path(): def test_parse_data_store_path(): expected = { - "project": "winkle", - "location": "nautilus", - "collection": "scallop", - "data_store": "abalone", + "project": "whelk", + "location": "octopus", + "collection": "oyster", + "data_store": "nudibranch", } path = ConversationsClient.data_store_path(**expected) @@ -11832,9 +11814,9 @@ def test_parse_data_store_path(): def test_document_path(): - project = "squid" - knowledge_base = "clam" - document = "whelk" + project = "cuttlefish" + knowledge_base = "mussel" + document = "winkle" expected = "projects/{project}/knowledgeBases/{knowledge_base}/documents/{document}".format( project=project, knowledge_base=knowledge_base, @@ -11846,9 +11828,9 @@ def test_document_path(): def test_parse_document_path(): expected = { - "project": "octopus", - "knowledge_base": "oyster", - "document": "nudibranch", + "project": "nautilus", + "knowledge_base": "scallop", + "document": "abalone", } path = ConversationsClient.document_path(**expected) @@ -11858,9 +11840,9 @@ def test_parse_document_path(): def test_generator_path(): - project = "cuttlefish" - location = "mussel" - generator = "winkle" + project = "squid" + location = "clam" + generator = "whelk" expected = "projects/{project}/locations/{location}/generators/{generator}".format( project=project, location=location, @@ -11872,9 +11854,9 @@ def test_generator_path(): def test_parse_generator_path(): expected = { - "project": "nautilus", - "location": "scallop", - "generator": "abalone", + "project": "octopus", + "location": "oyster", + "generator": "nudibranch", } path = ConversationsClient.generator_path(**expected) @@ -11884,8 +11866,8 @@ def test_parse_generator_path(): def test_knowledge_base_path(): - project = "squid" - knowledge_base = "clam" + project = "cuttlefish" + knowledge_base = "mussel" expected = "projects/{project}/knowledgeBases/{knowledge_base}".format( project=project, knowledge_base=knowledge_base, @@ -11896,8 +11878,8 @@ def test_knowledge_base_path(): def test_parse_knowledge_base_path(): expected = { - "project": "whelk", - "knowledge_base": "octopus", + "project": "winkle", + "knowledge_base": "nautilus", } path = ConversationsClient.knowledge_base_path(**expected) @@ -11907,9 +11889,9 @@ def test_parse_knowledge_base_path(): def test_message_path(): - project = "oyster" - conversation = "nudibranch" - message = "cuttlefish" + project = "scallop" + conversation = "abalone" + message = "squid" expected = ( "projects/{project}/conversations/{conversation}/messages/{message}".format( project=project, @@ -11923,9 +11905,9 @@ def test_message_path(): def test_parse_message_path(): expected = { - "project": "mussel", - "conversation": "winkle", - "message": "nautilus", + "project": "clam", + "conversation": "whelk", + "message": "octopus", } path = ConversationsClient.message_path(**expected) @@ -11935,9 +11917,9 @@ def test_parse_message_path(): def test_phrase_set_path(): - project = "scallop" - location = "abalone" - phrase_set = "squid" + project = "oyster" + location = "nudibranch" + phrase_set = "cuttlefish" expected = "projects/{project}/locations/{location}/phraseSets/{phrase_set}".format( project=project, location=location, @@ -11949,9 +11931,9 @@ def test_phrase_set_path(): def test_parse_phrase_set_path(): expected = { - "project": "clam", - "location": "whelk", - "phrase_set": "octopus", + "project": "mussel", + "location": "winkle", + "phrase_set": "nautilus", } path = ConversationsClient.phrase_set_path(**expected) @@ -11961,9 +11943,9 @@ def test_parse_phrase_set_path(): def test_tool_path(): - project = "oyster" - location = "nudibranch" - tool = "cuttlefish" + project = "scallop" + location = "abalone" + tool = "squid" expected = "projects/{project}/locations/{location}/tools/{tool}".format( project=project, location=location, @@ -11975,9 +11957,9 @@ def test_tool_path(): def test_parse_tool_path(): expected = { - "project": "mussel", - "location": "winkle", - "tool": "nautilus", + "project": "clam", + "location": "whelk", + "tool": "octopus", } path = ConversationsClient.tool_path(**expected) @@ -11987,10 +11969,10 @@ def test_parse_tool_path(): def test_toolset_path(): - project = "scallop" - location = "abalone" - app = "squid" - toolset = "clam" + project = "oyster" + location = "nudibranch" + app = "cuttlefish" + toolset = "mussel" expected = ( "projects/{project}/locations/{location}/apps/{app}/toolsets/{toolset}".format( project=project, @@ -12005,10 +11987,10 @@ def test_toolset_path(): def test_parse_toolset_path(): expected = { - "project": "whelk", - "location": "octopus", - "app": "oyster", - "toolset": "nudibranch", + "project": "winkle", + "location": "nautilus", + "app": "scallop", + "toolset": "abalone", } path = ConversationsClient.toolset_path(**expected) @@ -12018,7 +12000,7 @@ def test_parse_toolset_path(): def test_common_billing_account_path(): - billing_account = "cuttlefish" + billing_account = "squid" expected = "billingAccounts/{billing_account}".format( billing_account=billing_account, ) @@ -12028,7 +12010,7 @@ def test_common_billing_account_path(): def test_parse_common_billing_account_path(): expected = { - "billing_account": "mussel", + "billing_account": "clam", } path = ConversationsClient.common_billing_account_path(**expected) @@ -12038,7 +12020,7 @@ def test_parse_common_billing_account_path(): def test_common_folder_path(): - folder = "winkle" + folder = "whelk" expected = "folders/{folder}".format( folder=folder, ) @@ -12048,7 +12030,7 @@ def test_common_folder_path(): def test_parse_common_folder_path(): expected = { - "folder": "nautilus", + "folder": "octopus", } path = ConversationsClient.common_folder_path(**expected) @@ -12058,7 +12040,7 @@ def test_parse_common_folder_path(): def test_common_organization_path(): - organization = "scallop" + organization = "oyster" expected = "organizations/{organization}".format( organization=organization, ) @@ -12068,7 +12050,7 @@ def test_common_organization_path(): def test_parse_common_organization_path(): expected = { - "organization": "abalone", + "organization": "nudibranch", } path = ConversationsClient.common_organization_path(**expected) @@ -12078,7 +12060,7 @@ def test_parse_common_organization_path(): def test_common_project_path(): - project = "squid" + project = "cuttlefish" expected = "projects/{project}".format( project=project, ) @@ -12088,7 +12070,7 @@ def test_common_project_path(): def test_parse_common_project_path(): expected = { - "project": "clam", + "project": "mussel", } path = ConversationsClient.common_project_path(**expected) @@ -12098,8 +12080,8 @@ def test_parse_common_project_path(): def test_common_location_path(): - project = "whelk" - location = "octopus" + project = "winkle" + location = "nautilus" expected = "projects/{project}/locations/{location}".format( project=project, location=location, @@ -12110,8 +12092,8 @@ def test_common_location_path(): def test_parse_common_location_path(): expected = { - "project": "oyster", - "location": "nudibranch", + "project": "scallop", + "location": "abalone", } path = ConversationsClient.common_location_path(**expected) diff --git a/packages/google-cloud-dialogflow/tests/unit/gapic/dialogflow_v2beta1/test_generator_evaluations.py b/packages/google-cloud-dialogflow/tests/unit/gapic/dialogflow_v2beta1/test_generator_evaluations.py index da302d150b96..5b2357794325 100644 --- a/packages/google-cloud-dialogflow/tests/unit/gapic/dialogflow_v2beta1/test_generator_evaluations.py +++ b/packages/google-cloud-dialogflow/tests/unit/gapic/dialogflow_v2beta1/test_generator_evaluations.py @@ -4387,7 +4387,12 @@ def test_create_generator_evaluation_rest_call_success(request_type): {"ces_tool": "ces_tool_value", "confirmation_requirement": 1} ], "ces_app_specs": [ - {"ces_app": "ces_app_value", "confirmation_requirement": 1} + { + "ces_app": "ces_app_value", + "confirmation_requirement": 1, + "proactive_enabled": True, + "reactive_enabled": True, + } ], }, "summarization_metrics": { diff --git a/packages/google-cloud-dialogflow/tests/unit/gapic/dialogflow_v2beta1/test_generators.py b/packages/google-cloud-dialogflow/tests/unit/gapic/dialogflow_v2beta1/test_generators.py index 7a52a6dd9119..01dff22d1b68 100644 --- a/packages/google-cloud-dialogflow/tests/unit/gapic/dialogflow_v2beta1/test_generators.py +++ b/packages/google-cloud-dialogflow/tests/unit/gapic/dialogflow_v2beta1/test_generators.py @@ -4696,7 +4696,14 @@ def test_create_generator_rest_call_success(request_type): "ces_tool_specs": [ {"ces_tool": "ces_tool_value", "confirmation_requirement": 1} ], - "ces_app_specs": [{"ces_app": "ces_app_value", "confirmation_requirement": 1}], + "ces_app_specs": [ + { + "ces_app": "ces_app_value", + "confirmation_requirement": 1, + "proactive_enabled": True, + "reactive_enabled": True, + } + ], } # The version of a generated dependency at test runtime may differ from the version used during generation. # Delete any fields which are not present in the current runtime dependency @@ -5418,7 +5425,14 @@ def test_update_generator_rest_call_success(request_type): "ces_tool_specs": [ {"ces_tool": "ces_tool_value", "confirmation_requirement": 1} ], - "ces_app_specs": [{"ces_app": "ces_app_value", "confirmation_requirement": 1}], + "ces_app_specs": [ + { + "ces_app": "ces_app_value", + "confirmation_requirement": 1, + "proactive_enabled": True, + "reactive_enabled": True, + } + ], } # The version of a generated dependency at test runtime may differ from the version used during generation. # Delete any fields which are not present in the current runtime dependency diff --git a/packages/google-cloud-discoveryengine/docs/discoveryengine_v1beta/acl_config_service.rst b/packages/google-cloud-discoveryengine/docs/discoveryengine_v1beta/acl_config_service.rst new file mode 100644 index 000000000000..80fb59f726db --- /dev/null +++ b/packages/google-cloud-discoveryengine/docs/discoveryengine_v1beta/acl_config_service.rst @@ -0,0 +1,6 @@ +AclConfigService +---------------------------------- + +.. automodule:: google.cloud.discoveryengine_v1beta.services.acl_config_service + :members: + :inherited-members: diff --git a/packages/google-cloud-discoveryengine/docs/discoveryengine_v1beta/assistant_service.rst b/packages/google-cloud-discoveryengine/docs/discoveryengine_v1beta/assistant_service.rst new file mode 100644 index 000000000000..e617f2cf2bff --- /dev/null +++ b/packages/google-cloud-discoveryengine/docs/discoveryengine_v1beta/assistant_service.rst @@ -0,0 +1,10 @@ +AssistantService +---------------------------------- + +.. automodule:: google.cloud.discoveryengine_v1beta.services.assistant_service + :members: + :inherited-members: + +.. automodule:: google.cloud.discoveryengine_v1beta.services.assistant_service.pagers + :members: + :inherited-members: diff --git a/packages/google-cloud-discoveryengine/docs/discoveryengine_v1beta/cmek_config_service.rst b/packages/google-cloud-discoveryengine/docs/discoveryengine_v1beta/cmek_config_service.rst new file mode 100644 index 000000000000..6085286a93cb --- /dev/null +++ b/packages/google-cloud-discoveryengine/docs/discoveryengine_v1beta/cmek_config_service.rst @@ -0,0 +1,6 @@ +CmekConfigService +----------------------------------- + +.. automodule:: google.cloud.discoveryengine_v1beta.services.cmek_config_service + :members: + :inherited-members: diff --git a/packages/google-cloud-discoveryengine/docs/discoveryengine_v1beta/identity_mapping_store_service.rst b/packages/google-cloud-discoveryengine/docs/discoveryengine_v1beta/identity_mapping_store_service.rst new file mode 100644 index 000000000000..8bd083af7104 --- /dev/null +++ b/packages/google-cloud-discoveryengine/docs/discoveryengine_v1beta/identity_mapping_store_service.rst @@ -0,0 +1,10 @@ +IdentityMappingStoreService +--------------------------------------------- + +.. automodule:: google.cloud.discoveryengine_v1beta.services.identity_mapping_store_service + :members: + :inherited-members: + +.. automodule:: google.cloud.discoveryengine_v1beta.services.identity_mapping_store_service.pagers + :members: + :inherited-members: diff --git a/packages/google-cloud-discoveryengine/docs/discoveryengine_v1beta/license_config_service.rst b/packages/google-cloud-discoveryengine/docs/discoveryengine_v1beta/license_config_service.rst new file mode 100644 index 000000000000..2a63b2ae18be --- /dev/null +++ b/packages/google-cloud-discoveryengine/docs/discoveryengine_v1beta/license_config_service.rst @@ -0,0 +1,10 @@ +LicenseConfigService +-------------------------------------- + +.. automodule:: google.cloud.discoveryengine_v1beta.services.license_config_service + :members: + :inherited-members: + +.. automodule:: google.cloud.discoveryengine_v1beta.services.license_config_service.pagers + :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 82a6c914645c..b4a2af983c26 100644 --- a/packages/google-cloud-discoveryengine/docs/discoveryengine_v1beta/services_.rst +++ b/packages/google-cloud-discoveryengine/docs/discoveryengine_v1beta/services_.rst @@ -3,6 +3,9 @@ Services for Google Cloud Discoveryengine v1beta API .. toctree:: :maxdepth: 2 + acl_config_service + assistant_service + cmek_config_service completion_service control_service conversational_search_service @@ -11,6 +14,8 @@ Services for Google Cloud Discoveryengine v1beta API engine_service evaluation_service grounded_generation_service + identity_mapping_store_service + license_config_service project_service rank_service recommendation_service @@ -23,3 +28,5 @@ Services for Google Cloud Discoveryengine v1beta API session_service site_search_engine_service user_event_service + user_license_service + user_store_service diff --git a/packages/google-cloud-discoveryengine/docs/discoveryengine_v1beta/user_license_service.rst b/packages/google-cloud-discoveryengine/docs/discoveryengine_v1beta/user_license_service.rst new file mode 100644 index 000000000000..e38ec518bb9b --- /dev/null +++ b/packages/google-cloud-discoveryengine/docs/discoveryengine_v1beta/user_license_service.rst @@ -0,0 +1,10 @@ +UserLicenseService +------------------------------------ + +.. automodule:: google.cloud.discoveryengine_v1beta.services.user_license_service + :members: + :inherited-members: + +.. automodule:: google.cloud.discoveryengine_v1beta.services.user_license_service.pagers + :members: + :inherited-members: diff --git a/packages/google-cloud-discoveryengine/docs/discoveryengine_v1beta/user_store_service.rst b/packages/google-cloud-discoveryengine/docs/discoveryengine_v1beta/user_store_service.rst new file mode 100644 index 000000000000..158a414acac0 --- /dev/null +++ b/packages/google-cloud-discoveryengine/docs/discoveryengine_v1beta/user_store_service.rst @@ -0,0 +1,6 @@ +UserStoreService +---------------------------------- + +.. automodule:: google.cloud.discoveryengine_v1beta.services.user_store_service + :members: + :inherited-members: diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine/__init__.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine/__init__.py index 0f1477713e9c..b1096f22b83b 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine/__init__.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine/__init__.py @@ -18,6 +18,24 @@ __version__ = package_version.__version__ +from google.cloud.discoveryengine_v1beta.services.acl_config_service.async_client import ( + AclConfigServiceAsyncClient, +) +from google.cloud.discoveryengine_v1beta.services.acl_config_service.client import ( + AclConfigServiceClient, +) +from google.cloud.discoveryengine_v1beta.services.assistant_service.async_client import ( + AssistantServiceAsyncClient, +) +from google.cloud.discoveryengine_v1beta.services.assistant_service.client import ( + AssistantServiceClient, +) +from google.cloud.discoveryengine_v1beta.services.cmek_config_service.async_client import ( + CmekConfigServiceAsyncClient, +) +from google.cloud.discoveryengine_v1beta.services.cmek_config_service.client import ( + CmekConfigServiceClient, +) from google.cloud.discoveryengine_v1beta.services.completion_service.async_client import ( CompletionServiceAsyncClient, ) @@ -66,6 +84,18 @@ from google.cloud.discoveryengine_v1beta.services.grounded_generation_service.client import ( GroundedGenerationServiceClient, ) +from google.cloud.discoveryengine_v1beta.services.identity_mapping_store_service.async_client import ( + IdentityMappingStoreServiceAsyncClient, +) +from google.cloud.discoveryengine_v1beta.services.identity_mapping_store_service.client import ( + IdentityMappingStoreServiceClient, +) +from google.cloud.discoveryengine_v1beta.services.license_config_service.async_client import ( + LicenseConfigServiceAsyncClient, +) +from google.cloud.discoveryengine_v1beta.services.license_config_service.client import ( + LicenseConfigServiceClient, +) from google.cloud.discoveryengine_v1beta.services.project_service.async_client import ( ProjectServiceAsyncClient, ) @@ -138,18 +168,72 @@ from google.cloud.discoveryengine_v1beta.services.user_event_service.client import ( UserEventServiceClient, ) +from google.cloud.discoveryengine_v1beta.services.user_license_service.async_client import ( + UserLicenseServiceAsyncClient, +) +from google.cloud.discoveryengine_v1beta.services.user_license_service.client import ( + UserLicenseServiceClient, +) +from google.cloud.discoveryengine_v1beta.services.user_store_service.async_client import ( + UserStoreServiceAsyncClient, +) +from google.cloud.discoveryengine_v1beta.services.user_store_service.client import ( + UserStoreServiceClient, +) +from google.cloud.discoveryengine_v1beta.types.acl_config import AclConfig +from google.cloud.discoveryengine_v1beta.types.acl_config_service import ( + GetAclConfigRequest, + UpdateAclConfigRequest, +) +from google.cloud.discoveryengine_v1beta.types.agent_gateway_setting import ( + AgentGatewaySetting, +) from google.cloud.discoveryengine_v1beta.types.answer import Answer +from google.cloud.discoveryengine_v1beta.types.assist_answer import ( + AssistAnswer, + AssistantContent, + AssistantGroundedContent, +) +from google.cloud.discoveryengine_v1beta.types.assistant import Assistant +from google.cloud.discoveryengine_v1beta.types.assistant_service import ( + AssistUserMetadata, + CreateAssistantRequest, + DeleteAssistantRequest, + GetAssistantRequest, + ListAssistantsRequest, + ListAssistantsResponse, + StreamAssistRequest, + StreamAssistResponse, + UpdateAssistantRequest, +) from google.cloud.discoveryengine_v1beta.types.chunk import Chunk +from google.cloud.discoveryengine_v1beta.types.cmek_config_service import ( + CmekConfig, + DeleteCmekConfigMetadata, + DeleteCmekConfigRequest, + GetCmekConfigRequest, + ListCmekConfigsRequest, + ListCmekConfigsResponse, + SingleRegionKey, + UpdateCmekConfigMetadata, + UpdateCmekConfigRequest, +) from google.cloud.discoveryengine_v1beta.types.common import ( CustomAttribute, DoubleList, EmbeddingConfig, + HealthcareFhirConfig, + IdpConfig, IndustryVertical, Interval, + Principal, SearchAddOn, + SearchLinkPromotion, SearchTier, SearchUseCase, SolutionType, + SubscriptionTerm, + SubscriptionTier, UserInfo, ) from google.cloud.discoveryengine_v1beta.types.completion import ( @@ -161,6 +245,8 @@ AdvancedCompleteQueryResponse, CompleteQueryRequest, CompleteQueryResponse, + RemoveSuggestionRequest, + RemoveSuggestionResponse, ) from google.cloud.discoveryengine_v1beta.types.control import Condition, Control from google.cloud.discoveryengine_v1beta.types.control_service import ( @@ -201,6 +287,7 @@ CustomTuningModel, ) from google.cloud.discoveryengine_v1beta.types.data_store import ( + AdvancedSiteSearchConfig, DataStore, LanguageInfo, NaturalLanguageQueryUnderstandingConfig, @@ -259,10 +346,13 @@ ListEvaluationsRequest, ListEvaluationsResponse, ) +from google.cloud.discoveryengine_v1beta.types.feedback import Feedback from google.cloud.discoveryengine_v1beta.types.grounded_generation_service import ( CheckGroundingRequest, CheckGroundingResponse, CheckGroundingSpec, + Citation, + CitationMetadata, GenerateGroundedContentRequest, GenerateGroundedContentResponse, GroundedGenerationContent, @@ -272,6 +362,24 @@ GroundingConfig, GroundingFact, ) +from google.cloud.discoveryengine_v1beta.types.identity_mapping_store import ( + IdentityMappingEntry, + IdentityMappingStore, +) +from google.cloud.discoveryengine_v1beta.types.identity_mapping_store_service import ( + CreateIdentityMappingStoreRequest, + DeleteIdentityMappingStoreMetadata, + DeleteIdentityMappingStoreRequest, + GetIdentityMappingStoreRequest, + IdentityMappingEntryOperationMetadata, + ImportIdentityMappingsRequest, + ImportIdentityMappingsResponse, + ListIdentityMappingsRequest, + ListIdentityMappingsResponse, + ListIdentityMappingStoresRequest, + ListIdentityMappingStoresResponse, + PurgeIdentityMappingsRequest, +) from google.cloud.discoveryengine_v1beta.types.import_config import ( AlloyDbSource, BigQuerySource, @@ -299,6 +407,19 @@ ImportUserEventsResponse, SpannerSource, ) +from google.cloud.discoveryengine_v1beta.types.license_config import LicenseConfig +from google.cloud.discoveryengine_v1beta.types.license_config_service import ( + CreateLicenseConfigRequest, + DistributeLicenseConfigRequest, + DistributeLicenseConfigResponse, + GetLicenseConfigRequest, + ListLicenseConfigsRequest, + ListLicenseConfigsResponse, + RetractLicenseConfigRequest, + RetractLicenseConfigResponse, + UpdateLicenseConfigRequest, +) +from google.cloud.discoveryengine_v1beta.types.logging import ObservabilityConfig from google.cloud.discoveryengine_v1beta.types.project import Project from google.cloud.discoveryengine_v1beta.types.project_service import ( ProvisionProjectMetadata, @@ -328,6 +449,7 @@ RecommendRequest, RecommendResponse, ) +from google.cloud.discoveryengine_v1beta.types.safety import HarmCategory, SafetyRating from google.cloud.discoveryengine_v1beta.types.sample_query import SampleQuery from google.cloud.discoveryengine_v1beta.types.sample_query_service import ( CreateSampleQueryRequest, @@ -369,8 +491,13 @@ TrainCustomModelRequest, TrainCustomModelResponse, ) -from google.cloud.discoveryengine_v1beta.types.serving_config import ServingConfig +from google.cloud.discoveryengine_v1beta.types.serving_config import ( + AnswerGenerationSpec, + ServingConfig, +) from google.cloud.discoveryengine_v1beta.types.serving_config_service import ( + CreateServingConfigRequest, + DeleteServingConfigRequest, GetServingConfigRequest, ListServingConfigsRequest, ListServingConfigsResponse, @@ -432,8 +559,32 @@ CollectUserEventRequest, WriteUserEventRequest, ) +from google.cloud.discoveryengine_v1beta.types.user_license import ( + LicenseConfigUsageStats, + UserLicense, +) +from google.cloud.discoveryengine_v1beta.types.user_license_service import ( + BatchUpdateUserLicensesMetadata, + BatchUpdateUserLicensesRequest, + BatchUpdateUserLicensesResponse, + ListLicenseConfigsUsageStatsRequest, + ListLicenseConfigsUsageStatsResponse, + ListUserLicensesRequest, + ListUserLicensesResponse, +) +from google.cloud.discoveryengine_v1beta.types.user_store import UserStore +from google.cloud.discoveryengine_v1beta.types.user_store_service import ( + GetUserStoreRequest, + UpdateUserStoreRequest, +) __all__ = ( + "AclConfigServiceClient", + "AclConfigServiceAsyncClient", + "AssistantServiceClient", + "AssistantServiceAsyncClient", + "CmekConfigServiceClient", + "CmekConfigServiceAsyncClient", "CompletionServiceClient", "CompletionServiceAsyncClient", "ControlServiceClient", @@ -450,6 +601,10 @@ "EvaluationServiceAsyncClient", "GroundedGenerationServiceClient", "GroundedGenerationServiceAsyncClient", + "IdentityMappingStoreServiceClient", + "IdentityMappingStoreServiceAsyncClient", + "LicenseConfigServiceClient", + "LicenseConfigServiceAsyncClient", "ProjectServiceClient", "ProjectServiceAsyncClient", "RankServiceClient", @@ -474,24 +629,62 @@ "SiteSearchEngineServiceAsyncClient", "UserEventServiceClient", "UserEventServiceAsyncClient", + "UserLicenseServiceClient", + "UserLicenseServiceAsyncClient", + "UserStoreServiceClient", + "UserStoreServiceAsyncClient", + "AclConfig", + "GetAclConfigRequest", + "UpdateAclConfigRequest", + "AgentGatewaySetting", "Answer", + "AssistAnswer", + "AssistantContent", + "AssistantGroundedContent", + "Assistant", + "AssistUserMetadata", + "CreateAssistantRequest", + "DeleteAssistantRequest", + "GetAssistantRequest", + "ListAssistantsRequest", + "ListAssistantsResponse", + "StreamAssistRequest", + "StreamAssistResponse", + "UpdateAssistantRequest", "Chunk", + "CmekConfig", + "DeleteCmekConfigMetadata", + "DeleteCmekConfigRequest", + "GetCmekConfigRequest", + "ListCmekConfigsRequest", + "ListCmekConfigsResponse", + "SingleRegionKey", + "UpdateCmekConfigMetadata", + "UpdateCmekConfigRequest", "CustomAttribute", "DoubleList", "EmbeddingConfig", + "HealthcareFhirConfig", + "IdpConfig", "Interval", + "Principal", + "SearchLinkPromotion", "UserInfo", "IndustryVertical", "SearchAddOn", "SearchTier", "SearchUseCase", "SolutionType", + "SubscriptionTerm", + "SubscriptionTier", "CompletionSuggestion", "SuggestionDenyListEntry", "AdvancedCompleteQueryRequest", "AdvancedCompleteQueryResponse", "CompleteQueryRequest", "CompleteQueryResponse", + "RemoveSuggestionRequest", + "RemoveSuggestionResponse", "Condition", "Control", "CreateControlRequest", @@ -523,6 +716,7 @@ "UpdateConversationRequest", "UpdateSessionRequest", "CustomTuningModel", + "AdvancedSiteSearchConfig", "DataStore", "LanguageInfo", "NaturalLanguageQueryUnderstandingConfig", @@ -568,15 +762,32 @@ "ListEvaluationResultsResponse", "ListEvaluationsRequest", "ListEvaluationsResponse", + "Feedback", "CheckGroundingRequest", "CheckGroundingResponse", "CheckGroundingSpec", + "Citation", + "CitationMetadata", "GenerateGroundedContentRequest", "GenerateGroundedContentResponse", "GroundedGenerationContent", "FactChunk", "GroundingConfig", "GroundingFact", + "IdentityMappingEntry", + "IdentityMappingStore", + "CreateIdentityMappingStoreRequest", + "DeleteIdentityMappingStoreMetadata", + "DeleteIdentityMappingStoreRequest", + "GetIdentityMappingStoreRequest", + "IdentityMappingEntryOperationMetadata", + "ImportIdentityMappingsRequest", + "ImportIdentityMappingsResponse", + "ListIdentityMappingsRequest", + "ListIdentityMappingsResponse", + "ListIdentityMappingStoresRequest", + "ListIdentityMappingStoresResponse", + "PurgeIdentityMappingsRequest", "AlloyDbSource", "BigQuerySource", "BigtableOptions", @@ -602,6 +813,17 @@ "ImportUserEventsRequest", "ImportUserEventsResponse", "SpannerSource", + "LicenseConfig", + "CreateLicenseConfigRequest", + "DistributeLicenseConfigRequest", + "DistributeLicenseConfigResponse", + "GetLicenseConfigRequest", + "ListLicenseConfigsRequest", + "ListLicenseConfigsResponse", + "RetractLicenseConfigRequest", + "RetractLicenseConfigResponse", + "UpdateLicenseConfigRequest", + "ObservabilityConfig", "Project", "ProvisionProjectMetadata", "ProvisionProjectRequest", @@ -623,6 +845,8 @@ "RankResponse", "RecommendRequest", "RecommendResponse", + "SafetyRating", + "HarmCategory", "SampleQuery", "CreateSampleQueryRequest", "DeleteSampleQueryRequest", @@ -654,7 +878,10 @@ "TrainCustomModelMetadata", "TrainCustomModelRequest", "TrainCustomModelResponse", + "AnswerGenerationSpec", "ServingConfig", + "CreateServingConfigRequest", + "DeleteServingConfigRequest", "GetServingConfigRequest", "ListServingConfigsRequest", "ListServingConfigsResponse", @@ -708,4 +935,16 @@ "UserEvent", "CollectUserEventRequest", "WriteUserEventRequest", + "LicenseConfigUsageStats", + "UserLicense", + "BatchUpdateUserLicensesMetadata", + "BatchUpdateUserLicensesRequest", + "BatchUpdateUserLicensesResponse", + "ListLicenseConfigsUsageStatsRequest", + "ListLicenseConfigsUsageStatsResponse", + "ListUserLicensesRequest", + "ListUserLicensesResponse", + "UserStore", + "GetUserStoreRequest", + "UpdateUserStoreRequest", ) 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 33ec2f3deebb..2da7de3c92ab 100644 --- a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/__init__.py +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/__init__.py @@ -23,6 +23,18 @@ from importlib import metadata +from .services.acl_config_service import ( + AclConfigServiceAsyncClient, + AclConfigServiceClient, +) +from .services.assistant_service import ( + AssistantServiceAsyncClient, + AssistantServiceClient, +) +from .services.cmek_config_service import ( + CmekConfigServiceAsyncClient, + CmekConfigServiceClient, +) from .services.completion_service import ( CompletionServiceAsyncClient, CompletionServiceClient, @@ -46,6 +58,14 @@ GroundedGenerationServiceAsyncClient, GroundedGenerationServiceClient, ) +from .services.identity_mapping_store_service import ( + IdentityMappingStoreServiceAsyncClient, + IdentityMappingStoreServiceClient, +) +from .services.license_config_service import ( + LicenseConfigServiceAsyncClient, + LicenseConfigServiceClient, +) from .services.project_service import ProjectServiceAsyncClient, ProjectServiceClient from .services.rank_service import RankServiceAsyncClient, RankServiceClient from .services.recommendation_service import ( @@ -79,18 +99,63 @@ UserEventServiceAsyncClient, UserEventServiceClient, ) +from .services.user_license_service import ( + UserLicenseServiceAsyncClient, + UserLicenseServiceClient, +) +from .services.user_store_service import ( + UserStoreServiceAsyncClient, + UserStoreServiceClient, +) +from .types.acl_config import AclConfig +from .types.acl_config_service import GetAclConfigRequest, UpdateAclConfigRequest +from .types.agent_gateway_setting import AgentGatewaySetting from .types.answer import Answer +from .types.assist_answer import ( + AssistAnswer, + AssistantContent, + AssistantGroundedContent, +) +from .types.assistant import Assistant +from .types.assistant_service import ( + AssistUserMetadata, + CreateAssistantRequest, + DeleteAssistantRequest, + GetAssistantRequest, + ListAssistantsRequest, + ListAssistantsResponse, + StreamAssistRequest, + StreamAssistResponse, + UpdateAssistantRequest, +) from .types.chunk import Chunk +from .types.cmek_config_service import ( + CmekConfig, + DeleteCmekConfigMetadata, + DeleteCmekConfigRequest, + GetCmekConfigRequest, + ListCmekConfigsRequest, + ListCmekConfigsResponse, + SingleRegionKey, + UpdateCmekConfigMetadata, + UpdateCmekConfigRequest, +) from .types.common import ( CustomAttribute, DoubleList, EmbeddingConfig, + HealthcareFhirConfig, + IdpConfig, IndustryVertical, Interval, + Principal, SearchAddOn, + SearchLinkPromotion, SearchTier, SearchUseCase, SolutionType, + SubscriptionTerm, + SubscriptionTier, UserInfo, ) from .types.completion import CompletionSuggestion, SuggestionDenyListEntry @@ -99,6 +164,8 @@ AdvancedCompleteQueryResponse, CompleteQueryRequest, CompleteQueryResponse, + RemoveSuggestionRequest, + RemoveSuggestionResponse, ) from .types.control import Condition, Control from .types.control_service import ( @@ -137,6 +204,7 @@ ) from .types.custom_tuning_model import CustomTuningModel from .types.data_store import ( + AdvancedSiteSearchConfig, DataStore, LanguageInfo, NaturalLanguageQueryUnderstandingConfig, @@ -190,15 +258,33 @@ ListEvaluationsRequest, ListEvaluationsResponse, ) +from .types.feedback import Feedback from .types.grounded_generation_service import ( CheckGroundingRequest, CheckGroundingResponse, CheckGroundingSpec, + Citation, + CitationMetadata, GenerateGroundedContentRequest, GenerateGroundedContentResponse, GroundedGenerationContent, ) from .types.grounding import FactChunk, GroundingConfig, GroundingFact +from .types.identity_mapping_store import IdentityMappingEntry, IdentityMappingStore +from .types.identity_mapping_store_service import ( + CreateIdentityMappingStoreRequest, + DeleteIdentityMappingStoreMetadata, + DeleteIdentityMappingStoreRequest, + GetIdentityMappingStoreRequest, + IdentityMappingEntryOperationMetadata, + ImportIdentityMappingsRequest, + ImportIdentityMappingsResponse, + ListIdentityMappingsRequest, + ListIdentityMappingsResponse, + ListIdentityMappingStoresRequest, + ListIdentityMappingStoresResponse, + PurgeIdentityMappingsRequest, +) from .types.import_config import ( AlloyDbSource, BigQuerySource, @@ -226,6 +312,19 @@ ImportUserEventsResponse, SpannerSource, ) +from .types.license_config import LicenseConfig +from .types.license_config_service import ( + CreateLicenseConfigRequest, + DistributeLicenseConfigRequest, + DistributeLicenseConfigResponse, + GetLicenseConfigRequest, + ListLicenseConfigsRequest, + ListLicenseConfigsResponse, + RetractLicenseConfigRequest, + RetractLicenseConfigResponse, + UpdateLicenseConfigRequest, +) +from .types.logging import ObservabilityConfig from .types.project import Project from .types.project_service import ProvisionProjectMetadata, ProvisionProjectRequest from .types.purge_config import ( @@ -245,6 +344,7 @@ ) from .types.rank_service import RankingRecord, RankRequest, RankResponse from .types.recommendation_service import RecommendRequest, RecommendResponse +from .types.safety import HarmCategory, SafetyRating from .types.sample_query import SampleQuery from .types.sample_query_service import ( CreateSampleQueryRequest, @@ -283,8 +383,10 @@ TrainCustomModelRequest, TrainCustomModelResponse, ) -from .types.serving_config import ServingConfig +from .types.serving_config import AnswerGenerationSpec, ServingConfig from .types.serving_config_service import ( + CreateServingConfigRequest, + DeleteServingConfigRequest, GetServingConfigRequest, ListServingConfigsRequest, ListServingConfigsResponse, @@ -343,6 +445,18 @@ UserEvent, ) from .types.user_event_service import CollectUserEventRequest, WriteUserEventRequest +from .types.user_license import LicenseConfigUsageStats, UserLicense +from .types.user_license_service import ( + BatchUpdateUserLicensesMetadata, + BatchUpdateUserLicensesRequest, + BatchUpdateUserLicensesResponse, + ListLicenseConfigsUsageStatsRequest, + ListLicenseConfigsUsageStatsResponse, + ListUserLicensesRequest, + ListUserLicensesResponse, +) +from .types.user_store import UserStore +from .types.user_store_service import GetUserStoreRequest, UpdateUserStoreRequest if hasattr(api_core, "check_python_version") and hasattr( api_core, "check_dependency_versions" @@ -428,6 +542,9 @@ def _get_version(dependency_name): ) __all__ = ( + "AclConfigServiceAsyncClient", + "AssistantServiceAsyncClient", + "CmekConfigServiceAsyncClient", "CompletionServiceAsyncClient", "ControlServiceAsyncClient", "ConversationalSearchServiceAsyncClient", @@ -436,6 +553,8 @@ def _get_version(dependency_name): "EngineServiceAsyncClient", "EvaluationServiceAsyncClient", "GroundedGenerationServiceAsyncClient", + "IdentityMappingStoreServiceAsyncClient", + "LicenseConfigServiceAsyncClient", "ProjectServiceAsyncClient", "RankServiceAsyncClient", "RecommendationServiceAsyncClient", @@ -448,17 +567,33 @@ def _get_version(dependency_name): "SessionServiceAsyncClient", "SiteSearchEngineServiceAsyncClient", "UserEventServiceAsyncClient", + "UserLicenseServiceAsyncClient", + "UserStoreServiceAsyncClient", + "AclConfig", + "AclConfigServiceClient", "AdvancedCompleteQueryRequest", "AdvancedCompleteQueryResponse", + "AdvancedSiteSearchConfig", + "AgentGatewaySetting", "AlloyDbSource", "Answer", + "AnswerGenerationSpec", "AnswerQueryRequest", "AnswerQueryResponse", + "AssistAnswer", + "AssistUserMetadata", + "Assistant", + "AssistantContent", + "AssistantGroundedContent", + "AssistantServiceClient", "BatchCreateTargetSiteMetadata", "BatchCreateTargetSitesRequest", "BatchCreateTargetSitesResponse", "BatchGetDocumentsMetadataRequest", "BatchGetDocumentsMetadataResponse", + "BatchUpdateUserLicensesMetadata", + "BatchUpdateUserLicensesRequest", + "BatchUpdateUserLicensesResponse", "BatchVerifyTargetSitesMetadata", "BatchVerifyTargetSitesRequest", "BatchVerifyTargetSitesResponse", @@ -469,7 +604,11 @@ def _get_version(dependency_name): "CheckGroundingResponse", "CheckGroundingSpec", "Chunk", + "Citation", + "CitationMetadata", "CloudSqlSource", + "CmekConfig", + "CmekConfigServiceClient", "CollectUserEventRequest", "CompleteQueryRequest", "CompleteQueryResponse", @@ -485,6 +624,7 @@ def _get_version(dependency_name): "ConversationalSearchServiceClient", "ConverseConversationRequest", "ConverseConversationResponse", + "CreateAssistantRequest", "CreateControlRequest", "CreateConversationRequest", "CreateDataStoreMetadata", @@ -494,10 +634,13 @@ def _get_version(dependency_name): "CreateEngineRequest", "CreateEvaluationMetadata", "CreateEvaluationRequest", + "CreateIdentityMappingStoreRequest", + "CreateLicenseConfigRequest", "CreateSampleQueryRequest", "CreateSampleQuerySetRequest", "CreateSchemaMetadata", "CreateSchemaRequest", + "CreateServingConfigRequest", "CreateSessionRequest", "CreateSitemapMetadata", "CreateSitemapRequest", @@ -507,6 +650,9 @@ def _get_version(dependency_name): "CustomTuningModel", "DataStore", "DataStoreServiceClient", + "DeleteAssistantRequest", + "DeleteCmekConfigMetadata", + "DeleteCmekConfigRequest", "DeleteControlRequest", "DeleteConversationRequest", "DeleteDataStoreMetadata", @@ -514,10 +660,13 @@ def _get_version(dependency_name): "DeleteDocumentRequest", "DeleteEngineMetadata", "DeleteEngineRequest", + "DeleteIdentityMappingStoreMetadata", + "DeleteIdentityMappingStoreRequest", "DeleteSampleQueryRequest", "DeleteSampleQuerySetRequest", "DeleteSchemaMetadata", "DeleteSchemaRequest", + "DeleteServingConfigRequest", "DeleteSessionRequest", "DeleteSitemapMetadata", "DeleteSitemapRequest", @@ -526,6 +675,8 @@ def _get_version(dependency_name): "DisableAdvancedSiteSearchMetadata", "DisableAdvancedSiteSearchRequest", "DisableAdvancedSiteSearchResponse", + "DistributeLicenseConfigRequest", + "DistributeLicenseConfigResponse", "Document", "DocumentInfo", "DocumentProcessingConfig", @@ -540,6 +691,7 @@ def _get_version(dependency_name): "Evaluation", "EvaluationServiceClient", "FactChunk", + "Feedback", "FetchDomainVerificationStatusRequest", "FetchDomainVerificationStatusResponse", "FetchSitemapsRequest", @@ -549,13 +701,18 @@ def _get_version(dependency_name): "GcsSource", "GenerateGroundedContentRequest", "GenerateGroundedContentResponse", + "GetAclConfigRequest", "GetAnswerRequest", + "GetAssistantRequest", + "GetCmekConfigRequest", "GetControlRequest", "GetConversationRequest", "GetDataStoreRequest", "GetDocumentRequest", "GetEngineRequest", "GetEvaluationRequest", + "GetIdentityMappingStoreRequest", + "GetLicenseConfigRequest", "GetSampleQueryRequest", "GetSampleQuerySetRequest", "GetSchemaRequest", @@ -563,10 +720,18 @@ def _get_version(dependency_name): "GetSessionRequest", "GetSiteSearchEngineRequest", "GetTargetSiteRequest", + "GetUserStoreRequest", "GroundedGenerationContent", "GroundedGenerationServiceClient", "GroundingConfig", "GroundingFact", + "HarmCategory", + "HealthcareFhirConfig", + "IdentityMappingEntry", + "IdentityMappingEntryOperationMetadata", + "IdentityMappingStore", + "IdentityMappingStoreServiceClient", + "IdpConfig", "ImportCompletionSuggestionsMetadata", "ImportCompletionSuggestionsRequest", "ImportCompletionSuggestionsResponse", @@ -574,6 +739,8 @@ def _get_version(dependency_name): "ImportDocumentsRequest", "ImportDocumentsResponse", "ImportErrorConfig", + "ImportIdentityMappingsRequest", + "ImportIdentityMappingsResponse", "ImportSampleQueriesMetadata", "ImportSampleQueriesRequest", "ImportSampleQueriesResponse", @@ -586,6 +753,13 @@ def _get_version(dependency_name): "IndustryVertical", "Interval", "LanguageInfo", + "LicenseConfig", + "LicenseConfigServiceClient", + "LicenseConfigUsageStats", + "ListAssistantsRequest", + "ListAssistantsResponse", + "ListCmekConfigsRequest", + "ListCmekConfigsResponse", "ListControlsRequest", "ListControlsResponse", "ListConversationsRequest", @@ -602,6 +776,14 @@ def _get_version(dependency_name): "ListEvaluationResultsResponse", "ListEvaluationsRequest", "ListEvaluationsResponse", + "ListIdentityMappingStoresRequest", + "ListIdentityMappingStoresResponse", + "ListIdentityMappingsRequest", + "ListIdentityMappingsResponse", + "ListLicenseConfigsRequest", + "ListLicenseConfigsResponse", + "ListLicenseConfigsUsageStatsRequest", + "ListLicenseConfigsUsageStatsResponse", "ListSampleQueriesRequest", "ListSampleQueriesResponse", "ListSampleQuerySetsRequest", @@ -614,11 +796,15 @@ def _get_version(dependency_name): "ListSessionsResponse", "ListTargetSitesRequest", "ListTargetSitesResponse", + "ListUserLicensesRequest", + "ListUserLicensesResponse", "MediaInfo", "NaturalLanguageQueryUnderstandingConfig", + "ObservabilityConfig", "PageInfo", "PanelInfo", "PauseEngineRequest", + "Principal", "Project", "ProjectServiceClient", "ProvisionProjectMetadata", @@ -630,6 +816,7 @@ def _get_version(dependency_name): "PurgeDocumentsRequest", "PurgeDocumentsResponse", "PurgeErrorConfig", + "PurgeIdentityMappingsRequest", "PurgeSuggestionDenyListEntriesMetadata", "PurgeSuggestionDenyListEntriesRequest", "PurgeSuggestionDenyListEntriesResponse", @@ -648,8 +835,13 @@ def _get_version(dependency_name): "RecrawlUrisMetadata", "RecrawlUrisRequest", "RecrawlUrisResponse", + "RemoveSuggestionRequest", + "RemoveSuggestionResponse", "Reply", "ResumeEngineRequest", + "RetractLicenseConfigRequest", + "RetractLicenseConfigResponse", + "SafetyRating", "SampleQuery", "SampleQueryServiceClient", "SampleQuerySet", @@ -658,6 +850,7 @@ def _get_version(dependency_name): "SchemaServiceClient", "SearchAddOn", "SearchInfo", + "SearchLinkPromotion", "SearchRequest", "SearchResponse", "SearchServiceClient", @@ -668,12 +861,17 @@ def _get_version(dependency_name): "ServingConfigServiceClient", "Session", "SessionServiceClient", + "SingleRegionKey", "SiteSearchEngine", "SiteSearchEngineServiceClient", "SiteVerificationInfo", "Sitemap", "SolutionType", "SpannerSource", + "StreamAssistRequest", + "StreamAssistResponse", + "SubscriptionTerm", + "SubscriptionTier", "SuggestionDenyListEntry", "TargetSite", "TextInput", @@ -684,11 +882,16 @@ def _get_version(dependency_name): "TuneEngineMetadata", "TuneEngineRequest", "TuneEngineResponse", + "UpdateAclConfigRequest", + "UpdateAssistantRequest", + "UpdateCmekConfigMetadata", + "UpdateCmekConfigRequest", "UpdateControlRequest", "UpdateConversationRequest", "UpdateDataStoreRequest", "UpdateDocumentRequest", "UpdateEngineRequest", + "UpdateLicenseConfigRequest", "UpdateSampleQueryRequest", "UpdateSampleQuerySetRequest", "UpdateSchemaMetadata", @@ -697,9 +900,14 @@ def _get_version(dependency_name): "UpdateSessionRequest", "UpdateTargetSiteMetadata", "UpdateTargetSiteRequest", + "UpdateUserStoreRequest", "UserEvent", "UserEventServiceClient", "UserInfo", + "UserLicense", + "UserLicenseServiceClient", + "UserStore", + "UserStoreServiceClient", "WorkspaceConfig", "WriteUserEventRequest", ) 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 0aa1292af549..d1b856cd2f8a 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 @@ -5,6 +5,243 @@ "protoPackage": "google.cloud.discoveryengine.v1beta", "schema": "1.0", "services": { + "AclConfigService": { + "clients": { + "grpc": { + "libraryClient": "AclConfigServiceClient", + "rpcs": { + "GetAclConfig": { + "methods": [ + "get_acl_config" + ] + }, + "UpdateAclConfig": { + "methods": [ + "update_acl_config" + ] + } + } + }, + "grpc-async": { + "libraryClient": "AclConfigServiceAsyncClient", + "rpcs": { + "GetAclConfig": { + "methods": [ + "get_acl_config" + ] + }, + "UpdateAclConfig": { + "methods": [ + "update_acl_config" + ] + } + } + }, + "rest": { + "libraryClient": "AclConfigServiceClient", + "rpcs": { + "GetAclConfig": { + "methods": [ + "get_acl_config" + ] + }, + "UpdateAclConfig": { + "methods": [ + "update_acl_config" + ] + } + } + } + } + }, + "AssistantService": { + "clients": { + "grpc": { + "libraryClient": "AssistantServiceClient", + "rpcs": { + "CreateAssistant": { + "methods": [ + "create_assistant" + ] + }, + "DeleteAssistant": { + "methods": [ + "delete_assistant" + ] + }, + "GetAssistant": { + "methods": [ + "get_assistant" + ] + }, + "ListAssistants": { + "methods": [ + "list_assistants" + ] + }, + "StreamAssist": { + "methods": [ + "stream_assist" + ] + }, + "UpdateAssistant": { + "methods": [ + "update_assistant" + ] + } + } + }, + "grpc-async": { + "libraryClient": "AssistantServiceAsyncClient", + "rpcs": { + "CreateAssistant": { + "methods": [ + "create_assistant" + ] + }, + "DeleteAssistant": { + "methods": [ + "delete_assistant" + ] + }, + "GetAssistant": { + "methods": [ + "get_assistant" + ] + }, + "ListAssistants": { + "methods": [ + "list_assistants" + ] + }, + "StreamAssist": { + "methods": [ + "stream_assist" + ] + }, + "UpdateAssistant": { + "methods": [ + "update_assistant" + ] + } + } + }, + "rest": { + "libraryClient": "AssistantServiceClient", + "rpcs": { + "CreateAssistant": { + "methods": [ + "create_assistant" + ] + }, + "DeleteAssistant": { + "methods": [ + "delete_assistant" + ] + }, + "GetAssistant": { + "methods": [ + "get_assistant" + ] + }, + "ListAssistants": { + "methods": [ + "list_assistants" + ] + }, + "StreamAssist": { + "methods": [ + "stream_assist" + ] + }, + "UpdateAssistant": { + "methods": [ + "update_assistant" + ] + } + } + } + } + }, + "CmekConfigService": { + "clients": { + "grpc": { + "libraryClient": "CmekConfigServiceClient", + "rpcs": { + "DeleteCmekConfig": { + "methods": [ + "delete_cmek_config" + ] + }, + "GetCmekConfig": { + "methods": [ + "get_cmek_config" + ] + }, + "ListCmekConfigs": { + "methods": [ + "list_cmek_configs" + ] + }, + "UpdateCmekConfig": { + "methods": [ + "update_cmek_config" + ] + } + } + }, + "grpc-async": { + "libraryClient": "CmekConfigServiceAsyncClient", + "rpcs": { + "DeleteCmekConfig": { + "methods": [ + "delete_cmek_config" + ] + }, + "GetCmekConfig": { + "methods": [ + "get_cmek_config" + ] + }, + "ListCmekConfigs": { + "methods": [ + "list_cmek_configs" + ] + }, + "UpdateCmekConfig": { + "methods": [ + "update_cmek_config" + ] + } + } + }, + "rest": { + "libraryClient": "CmekConfigServiceClient", + "rpcs": { + "DeleteCmekConfig": { + "methods": [ + "delete_cmek_config" + ] + }, + "GetCmekConfig": { + "methods": [ + "get_cmek_config" + ] + }, + "ListCmekConfigs": { + "methods": [ + "list_cmek_configs" + ] + }, + "UpdateCmekConfig": { + "methods": [ + "update_cmek_config" + ] + } + } + } + } + }, "CompletionService": { "clients": { "grpc": { @@ -39,6 +276,11 @@ "methods": [ "purge_suggestion_deny_list_entries" ] + }, + "RemoveSuggestion": { + "methods": [ + "remove_suggestion" + ] } } }, @@ -74,6 +316,11 @@ "methods": [ "purge_suggestion_deny_list_entries" ] + }, + "RemoveSuggestion": { + "methods": [ + "remove_suggestion" + ] } } }, @@ -109,6 +356,11 @@ "methods": [ "purge_suggestion_deny_list_entries" ] + }, + "RemoveSuggestion": { + "methods": [ + "remove_suggestion" + ] } } } @@ -268,6 +520,11 @@ "list_sessions" ] }, + "StreamAnswerQuery": { + "methods": [ + "stream_answer_query" + ] + }, "UpdateConversation": { "methods": [ "update_conversation" @@ -338,6 +595,11 @@ "list_sessions" ] }, + "StreamAnswerQuery": { + "methods": [ + "stream_answer_query" + ] + }, "UpdateConversation": { "methods": [ "update_conversation" @@ -408,6 +670,11 @@ "list_sessions" ] }, + "StreamAnswerQuery": { + "methods": [ + "stream_answer_query" + ] + }, "UpdateConversation": { "methods": [ "update_conversation" @@ -675,6 +942,11 @@ "get_engine" ] }, + "GetIamPolicy": { + "methods": [ + "get_iam_policy" + ] + }, "ListEngines": { "methods": [ "list_engines" @@ -690,6 +962,11 @@ "resume_engine" ] }, + "SetIamPolicy": { + "methods": [ + "set_iam_policy" + ] + }, "TuneEngine": { "methods": [ "tune_engine" @@ -720,6 +997,11 @@ "get_engine" ] }, + "GetIamPolicy": { + "methods": [ + "get_iam_policy" + ] + }, "ListEngines": { "methods": [ "list_engines" @@ -735,6 +1017,11 @@ "resume_engine" ] }, + "SetIamPolicy": { + "methods": [ + "set_iam_policy" + ] + }, "TuneEngine": { "methods": [ "tune_engine" @@ -765,6 +1052,11 @@ "get_engine" ] }, + "GetIamPolicy": { + "methods": [ + "get_iam_policy" + ] + }, "ListEngines": { "methods": [ "list_engines" @@ -780,6 +1072,11 @@ "resume_engine" ] }, + "SetIamPolicy": { + "methods": [ + "set_iam_policy" + ] + }, "TuneEngine": { "methods": [ "tune_engine" @@ -937,6 +1234,239 @@ } } }, + "IdentityMappingStoreService": { + "clients": { + "grpc": { + "libraryClient": "IdentityMappingStoreServiceClient", + "rpcs": { + "CreateIdentityMappingStore": { + "methods": [ + "create_identity_mapping_store" + ] + }, + "DeleteIdentityMappingStore": { + "methods": [ + "delete_identity_mapping_store" + ] + }, + "GetIdentityMappingStore": { + "methods": [ + "get_identity_mapping_store" + ] + }, + "ImportIdentityMappings": { + "methods": [ + "import_identity_mappings" + ] + }, + "ListIdentityMappingStores": { + "methods": [ + "list_identity_mapping_stores" + ] + }, + "ListIdentityMappings": { + "methods": [ + "list_identity_mappings" + ] + }, + "PurgeIdentityMappings": { + "methods": [ + "purge_identity_mappings" + ] + } + } + }, + "grpc-async": { + "libraryClient": "IdentityMappingStoreServiceAsyncClient", + "rpcs": { + "CreateIdentityMappingStore": { + "methods": [ + "create_identity_mapping_store" + ] + }, + "DeleteIdentityMappingStore": { + "methods": [ + "delete_identity_mapping_store" + ] + }, + "GetIdentityMappingStore": { + "methods": [ + "get_identity_mapping_store" + ] + }, + "ImportIdentityMappings": { + "methods": [ + "import_identity_mappings" + ] + }, + "ListIdentityMappingStores": { + "methods": [ + "list_identity_mapping_stores" + ] + }, + "ListIdentityMappings": { + "methods": [ + "list_identity_mappings" + ] + }, + "PurgeIdentityMappings": { + "methods": [ + "purge_identity_mappings" + ] + } + } + }, + "rest": { + "libraryClient": "IdentityMappingStoreServiceClient", + "rpcs": { + "CreateIdentityMappingStore": { + "methods": [ + "create_identity_mapping_store" + ] + }, + "DeleteIdentityMappingStore": { + "methods": [ + "delete_identity_mapping_store" + ] + }, + "GetIdentityMappingStore": { + "methods": [ + "get_identity_mapping_store" + ] + }, + "ImportIdentityMappings": { + "methods": [ + "import_identity_mappings" + ] + }, + "ListIdentityMappingStores": { + "methods": [ + "list_identity_mapping_stores" + ] + }, + "ListIdentityMappings": { + "methods": [ + "list_identity_mappings" + ] + }, + "PurgeIdentityMappings": { + "methods": [ + "purge_identity_mappings" + ] + } + } + } + } + }, + "LicenseConfigService": { + "clients": { + "grpc": { + "libraryClient": "LicenseConfigServiceClient", + "rpcs": { + "CreateLicenseConfig": { + "methods": [ + "create_license_config" + ] + }, + "DistributeLicenseConfig": { + "methods": [ + "distribute_license_config" + ] + }, + "GetLicenseConfig": { + "methods": [ + "get_license_config" + ] + }, + "ListLicenseConfigs": { + "methods": [ + "list_license_configs" + ] + }, + "RetractLicenseConfig": { + "methods": [ + "retract_license_config" + ] + }, + "UpdateLicenseConfig": { + "methods": [ + "update_license_config" + ] + } + } + }, + "grpc-async": { + "libraryClient": "LicenseConfigServiceAsyncClient", + "rpcs": { + "CreateLicenseConfig": { + "methods": [ + "create_license_config" + ] + }, + "DistributeLicenseConfig": { + "methods": [ + "distribute_license_config" + ] + }, + "GetLicenseConfig": { + "methods": [ + "get_license_config" + ] + }, + "ListLicenseConfigs": { + "methods": [ + "list_license_configs" + ] + }, + "RetractLicenseConfig": { + "methods": [ + "retract_license_config" + ] + }, + "UpdateLicenseConfig": { + "methods": [ + "update_license_config" + ] + } + } + }, + "rest": { + "libraryClient": "LicenseConfigServiceClient", + "rpcs": { + "CreateLicenseConfig": { + "methods": [ + "create_license_config" + ] + }, + "DistributeLicenseConfig": { + "methods": [ + "distribute_license_config" + ] + }, + "GetLicenseConfig": { + "methods": [ + "get_license_config" + ] + }, + "ListLicenseConfigs": { + "methods": [ + "list_license_configs" + ] + }, + "RetractLicenseConfig": { + "methods": [ + "retract_license_config" + ] + }, + "UpdateLicenseConfig": { + "methods": [ + "update_license_config" + ] + } + } + } + } + }, "ProjectService": { "clients": { "grpc": { @@ -1439,6 +1969,16 @@ "grpc": { "libraryClient": "ServingConfigServiceClient", "rpcs": { + "CreateServingConfig": { + "methods": [ + "create_serving_config" + ] + }, + "DeleteServingConfig": { + "methods": [ + "delete_serving_config" + ] + }, "GetServingConfig": { "methods": [ "get_serving_config" @@ -1459,6 +1999,16 @@ "grpc-async": { "libraryClient": "ServingConfigServiceAsyncClient", "rpcs": { + "CreateServingConfig": { + "methods": [ + "create_serving_config" + ] + }, + "DeleteServingConfig": { + "methods": [ + "delete_serving_config" + ] + }, "GetServingConfig": { "methods": [ "get_serving_config" @@ -1479,6 +2029,16 @@ "rest": { "libraryClient": "ServingConfigServiceClient", "rpcs": { + "CreateServingConfig": { + "methods": [ + "create_serving_config" + ] + }, + "DeleteServingConfig": { + "methods": [ + "delete_serving_config" + ] + }, "GetServingConfig": { "methods": [ "get_serving_config" @@ -1914,6 +2474,119 @@ } } } + }, + "UserLicenseService": { + "clients": { + "grpc": { + "libraryClient": "UserLicenseServiceClient", + "rpcs": { + "BatchUpdateUserLicenses": { + "methods": [ + "batch_update_user_licenses" + ] + }, + "ListLicenseConfigsUsageStats": { + "methods": [ + "list_license_configs_usage_stats" + ] + }, + "ListUserLicenses": { + "methods": [ + "list_user_licenses" + ] + } + } + }, + "grpc-async": { + "libraryClient": "UserLicenseServiceAsyncClient", + "rpcs": { + "BatchUpdateUserLicenses": { + "methods": [ + "batch_update_user_licenses" + ] + }, + "ListLicenseConfigsUsageStats": { + "methods": [ + "list_license_configs_usage_stats" + ] + }, + "ListUserLicenses": { + "methods": [ + "list_user_licenses" + ] + } + } + }, + "rest": { + "libraryClient": "UserLicenseServiceClient", + "rpcs": { + "BatchUpdateUserLicenses": { + "methods": [ + "batch_update_user_licenses" + ] + }, + "ListLicenseConfigsUsageStats": { + "methods": [ + "list_license_configs_usage_stats" + ] + }, + "ListUserLicenses": { + "methods": [ + "list_user_licenses" + ] + } + } + } + } + }, + "UserStoreService": { + "clients": { + "grpc": { + "libraryClient": "UserStoreServiceClient", + "rpcs": { + "GetUserStore": { + "methods": [ + "get_user_store" + ] + }, + "UpdateUserStore": { + "methods": [ + "update_user_store" + ] + } + } + }, + "grpc-async": { + "libraryClient": "UserStoreServiceAsyncClient", + "rpcs": { + "GetUserStore": { + "methods": [ + "get_user_store" + ] + }, + "UpdateUserStore": { + "methods": [ + "update_user_store" + ] + } + } + }, + "rest": { + "libraryClient": "UserStoreServiceClient", + "rpcs": { + "GetUserStore": { + "methods": [ + "get_user_store" + ] + }, + "UpdateUserStore": { + "methods": [ + "update_user_store" + ] + } + } + } + } } } } diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/acl_config_service/__init__.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/acl_config_service/__init__.py new file mode 100644 index 000000000000..1f391c0152a8 --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/acl_config_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2026 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 AclConfigServiceAsyncClient +from .client import AclConfigServiceClient + +__all__ = ( + "AclConfigServiceClient", + "AclConfigServiceAsyncClient", +) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/acl_config_service/async_client.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/acl_config_service/async_client.py new file mode 100644 index 000000000000..a86139088ef3 --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/acl_config_service/async_client.py @@ -0,0 +1,702 @@ +# -*- coding: utf-8 -*- +# Copyright 2026 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 logging as std_logging +import re +from collections import OrderedDict +from typing import ( + Callable, + Dict, + Mapping, + MutableMapping, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, +) + +import google.protobuf +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 ( + acl_config, + acl_config_service, + common, +) + +from .client import AclConfigServiceClient +from .transports.base import DEFAULT_CLIENT_INFO, AclConfigServiceTransport +from .transports.grpc_asyncio import AclConfigServiceGrpcAsyncIOTransport + +try: + from google.api_core import client_logging # type: ignore + + CLIENT_LOGGING_SUPPORTED = True # pragma: NO COVER +except ImportError: # pragma: NO COVER + CLIENT_LOGGING_SUPPORTED = False + +_LOGGER = std_logging.getLogger(__name__) + + +class AclConfigServiceAsyncClient: + """Service for managing Acl Configuration.""" + + _client: AclConfigServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = AclConfigServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = AclConfigServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = AclConfigServiceClient._DEFAULT_ENDPOINT_TEMPLATE + _DEFAULT_UNIVERSE = AclConfigServiceClient._DEFAULT_UNIVERSE + + acl_config_path = staticmethod(AclConfigServiceClient.acl_config_path) + parse_acl_config_path = staticmethod(AclConfigServiceClient.parse_acl_config_path) + common_billing_account_path = staticmethod( + AclConfigServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + AclConfigServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod(AclConfigServiceClient.common_folder_path) + parse_common_folder_path = staticmethod( + AclConfigServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + AclConfigServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + AclConfigServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod(AclConfigServiceClient.common_project_path) + parse_common_project_path = staticmethod( + AclConfigServiceClient.parse_common_project_path + ) + common_location_path = staticmethod(AclConfigServiceClient.common_location_path) + parse_common_location_path = staticmethod( + AclConfigServiceClient.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: + AclConfigServiceAsyncClient: The constructed client. + """ + sa_info_func = ( + AclConfigServiceClient.from_service_account_info.__func__ # type: ignore + ) + return sa_info_func(AclConfigServiceAsyncClient, info, *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: + AclConfigServiceAsyncClient: The constructed client. + """ + sa_file_func = ( + AclConfigServiceClient.from_service_account_file.__func__ # type: ignore + ) + return sa_file_func(AclConfigServiceAsyncClient, filename, *args, **kwargs) + + 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 AclConfigServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> AclConfigServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AclConfigServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self) -> str: + """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 = AclConfigServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, AclConfigServiceTransport, Callable[..., AclConfigServiceTransport] + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the acl config service async client. + + Args: + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + transport (Optional[Union[str,AclConfigServiceTransport,Callable[..., AclConfigServiceTransport]]]): + The transport to use, or a Callable that constructs and returns a new transport to use. + If a Callable is given, it will be called with the same set of initialization + arguments as used in the AclConfigServiceTransport constructor. + If set to None, a transport is chosen automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): + Custom options for the client. + + 1. The ``api_endpoint`` property can be used to override the + default endpoint provided by the client when ``transport`` is + not explicitly provided. Only if this property is not set and + ``transport`` was not explicitly provided, the endpoint is + determined by the GOOGLE_API_USE_MTLS_ENDPOINT environment + variable, which have one of the following values: + "always" (always use the default mTLS endpoint), "never" (always + use the default regular endpoint) and "auto" (auto-switch to the + default mTLS endpoint if client certificate is present; this is + the default value). + + 2. If the GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide a client certificate for mTLS transport. If + not provided, the default SSL client certificate will be used if + present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not + set, no client certificate will be used. + + 3. The ``universe_domain`` property can be used to override the + default "googleapis.com" universe. Note that ``api_endpoint`` + property still takes precedence; and ``universe_domain`` is + currently not supported for mTLS. + + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + + Raises: + google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport + creation failed for any reason. + """ + self._client = AclConfigServiceClient( + credentials=credentials, + transport=transport, + client_options=client_options, + client_info=client_info, + ) + + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + std_logging.DEBUG + ): # pragma: NO COVER + _LOGGER.debug( + "Created client `google.cloud.discoveryengine_v1beta.AclConfigServiceAsyncClient`.", + extra={ + "serviceName": "google.cloud.discoveryengine.v1beta.AclConfigService", + "universeDomain": getattr( + self._client._transport._credentials, "universe_domain", "" + ), + "credentialsType": f"{type(self._client._transport._credentials).__module__}.{type(self._client._transport._credentials).__qualname__}", + "credentialsInfo": getattr( + self.transport._credentials, "get_cred_info", lambda: None + )(), + } + if hasattr(self._client._transport, "_credentials") + else { + "serviceName": "google.cloud.discoveryengine.v1beta.AclConfigService", + "credentialsType": None, + }, + ) + + async def update_acl_config( + self, + request: Optional[ + Union[acl_config_service.UpdateAclConfigRequest, dict] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> acl_config.AclConfig: + r"""Default ACL configuration for use in a location of a + customer's project. Updates will only reflect to new + data stores. Existing data stores will still use the old + value. + + .. 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_acl_config(): + # Create a client + client = discoveryengine_v1beta.AclConfigServiceAsyncClient() + + # Initialize request argument(s) + request = discoveryengine_v1beta.UpdateAclConfigRequest( + ) + + # Make the request + response = await client.update_acl_config(request=request) + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.discoveryengine_v1beta.types.UpdateAclConfigRequest, dict]]): + The request object. Request message for UpdateAclConfig + 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + google.cloud.discoveryengine_v1beta.types.AclConfig: + Access Control Configuration. + """ + # Create or coerce a protobuf request object. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, acl_config_service.UpdateAclConfigRequest): + request = acl_config_service.UpdateAclConfigRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.update_acl_config + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("acl_config.name", request.acl_config.name),) + ), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def get_acl_config( + self, + request: Optional[Union[acl_config_service.GetAclConfigRequest, dict]] = None, + *, + name: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> acl_config.AclConfig: + r"""Gets the + [AclConfig][google.cloud.discoveryengine.v1beta.AclConfig]. + + .. 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_acl_config(): + # Create a client + client = discoveryengine_v1beta.AclConfigServiceAsyncClient() + + # Initialize request argument(s) + request = discoveryengine_v1beta.GetAclConfigRequest( + name="name_value", + ) + + # Make the request + response = await client.get_acl_config(request=request) + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.discoveryengine_v1beta.types.GetAclConfigRequest, dict]]): + The request object. Request message for + GetAclConfigRequest method. + name (:class:`str`): + Required. Resource name of + [AclConfig][google.cloud.discoveryengine.v1beta.AclConfig], + such as ``projects/*/locations/*/aclConfig``. + + If the caller does not have permission to access the + [AclConfig][google.cloud.discoveryengine.v1beta.AclConfig], + regardless of whether or not it exists, a + PERMISSION_DENIED 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + google.cloud.discoveryengine_v1beta.types.AclConfig: + Access Control Configuration. + """ + # 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. + flattened_params = [name] + has_flattened_params = ( + len([param for param in flattened_params if param is not None]) > 0 + ) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, acl_config_service.GetAclConfigRequest): + request = acl_config_service.GetAclConfigRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if name is not None: + request.name = name + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.get_acl_config + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def list_operations( + self, + request: Optional[Union[operations_pb2.ListOperationsRequest, dict]] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + 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 request is None: + request_pb = operations_pb2.ListOperationsRequest() + elif isinstance(request, dict): + request_pb = operations_pb2.ListOperationsRequest(**request) + else: + request_pb = request + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self.transport._wrapped_methods[self._client._transport.list_operations] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request_pb.name),)), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request_pb, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def get_operation( + self, + request: Optional[Union[operations_pb2.GetOperationRequest, dict]] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + 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 request is None: + request_pb = operations_pb2.GetOperationRequest() + elif isinstance(request, dict): + request_pb = operations_pb2.GetOperationRequest(**request) + else: + request_pb = request + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self.transport._wrapped_methods[self._client._transport.get_operation] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request_pb.name),)), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request_pb, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def cancel_operation( + self, + request: Optional[Union[operations_pb2.CancelOperationRequest, dict]] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> None: + r"""Starts asynchronous cancellation on a long-running operation. + + The server makes a best effort to cancel the operation, but success + is not guaranteed. If the server doesn't support this method, it returns + `google.rpc.Code.UNIMPLEMENTED`. + + Args: + request (:class:`~.operations_pb2.CancelOperationRequest`): + The request object. Request message for + `CancelOperation` 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + Returns: + None + """ + # 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 request is None: + request_pb = operations_pb2.CancelOperationRequest() + elif isinstance(request, dict): + request_pb = operations_pb2.CancelOperationRequest(**request) + else: + request_pb = request + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self.transport._wrapped_methods[self._client._transport.cancel_operation] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request_pb.name),)), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + await rpc( + request_pb, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + async def __aenter__(self) -> "AclConfigServiceAsyncClient": + 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__ +) + +if hasattr(DEFAULT_CLIENT_INFO, "protobuf_runtime_version"): # pragma: NO COVER + DEFAULT_CLIENT_INFO.protobuf_runtime_version = google.protobuf.__version__ + + +__all__ = ("AclConfigServiceAsyncClient",) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/acl_config_service/client.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/acl_config_service/client.py new file mode 100644 index 000000000000..62f9d96893d3 --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/acl_config_service/client.py @@ -0,0 +1,1143 @@ +# -*- coding: utf-8 -*- +# Copyright 2026 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 json +import logging as std_logging +import os +import re +import warnings +from collections import OrderedDict +from http import HTTPStatus +from typing import ( + Callable, + Dict, + Mapping, + MutableMapping, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) + +import google.protobuf +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 + +try: + from google.api_core import client_logging # type: ignore + + CLIENT_LOGGING_SUPPORTED = True # pragma: NO COVER +except ImportError: # pragma: NO COVER + CLIENT_LOGGING_SUPPORTED = False + +_LOGGER = std_logging.getLogger(__name__) + +from google.cloud.location import locations_pb2 # type: ignore +from google.longrunning import operations_pb2 # type: ignore + +from google.cloud.discoveryengine_v1beta.types import ( + acl_config, + acl_config_service, + common, +) + +from .transports.base import DEFAULT_CLIENT_INFO, AclConfigServiceTransport +from .transports.grpc import AclConfigServiceGrpcTransport +from .transports.grpc_asyncio import AclConfigServiceGrpcAsyncIOTransport +from .transports.rest import AclConfigServiceRestTransport + + +class AclConfigServiceClientMeta(type): + """Metaclass for the AclConfigService 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[AclConfigServiceTransport]] + _transport_registry["grpc"] = AclConfigServiceGrpcTransport + _transport_registry["grpc_asyncio"] = AclConfigServiceGrpcAsyncIOTransport + _transport_registry["rest"] = AclConfigServiceRestTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[AclConfigServiceTransport]: + """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 AclConfigServiceClient(metaclass=AclConfigServiceClientMeta): + """Service for managing Acl Configuration.""" + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint) -> Optional[str]: + """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: + Optional[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) + if m is None: + # Could not parse api_endpoint; return as-is. + return 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" + + @staticmethod + def _use_client_cert_effective(): + """Returns whether client certificate should be used for mTLS if the + google-auth version supports should_use_client_cert automatic mTLS enablement. + + Alternatively, read from the GOOGLE_API_USE_CLIENT_CERTIFICATE env var. + + Returns: + bool: whether client certificate should be used for mTLS + Raises: + ValueError: (If using a version of google-auth without should_use_client_cert and + GOOGLE_API_USE_CLIENT_CERTIFICATE is set to an unexpected value.) + """ + # check if google-auth version supports should_use_client_cert for automatic mTLS enablement + if hasattr(mtls, "should_use_client_cert"): # pragma: NO COVER + return mtls.should_use_client_cert() + else: # pragma: NO COVER + # if unsupported, fallback to reading from env var + use_client_cert_str = os.getenv( + "GOOGLE_API_USE_CLIENT_CERTIFICATE", "false" + ).lower() + if use_client_cert_str not in ("true", "false"): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be" + " either `true` or `false`" + ) + return use_client_cert_str == "true" + + @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: + AclConfigServiceClient: 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: + AclConfigServiceClient: 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) -> AclConfigServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AclConfigServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def acl_config_path( + project: str, + location: str, + ) -> str: + """Returns a fully-qualified acl_config string.""" + return "projects/{project}/locations/{location}/aclConfig".format( + project=project, + location=location, + ) + + @staticmethod + def parse_acl_config_path(path: str) -> Dict[str, str]: + """Parses a acl_config path into its component segments.""" + m = re.match( + r"^projects/(?P.+?)/locations/(?P.+?)/aclConfig$", 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 = AclConfigServiceClient._use_client_cert_effective() + use_mtls_endpoint = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto") + 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: + 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 = AclConfigServiceClient._use_client_cert_effective() + use_mtls_endpoint = os.getenv("GOOGLE_API_USE_MTLS_ENDPOINT", "auto").lower() + universe_domain_env = os.getenv("GOOGLE_CLOUD_UNIVERSE_DOMAIN") + 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, 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 + ) -> str: + """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 = AclConfigServiceClient._DEFAULT_UNIVERSE + if universe_domain != _default_universe: + raise MutualTLSChannelError( + f"mTLS is not supported in any universe other than {_default_universe}." + ) + api_endpoint = AclConfigServiceClient.DEFAULT_MTLS_ENDPOINT + else: + api_endpoint = AclConfigServiceClient._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 = AclConfigServiceClient._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 + + 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. + """ + + # NOTE (b/349488459): universe validation is disabled until further notice. + return True + + def _add_cred_info_for_auth_errors( + self, error: core_exceptions.GoogleAPICallError + ) -> None: + """Adds credential info string to error details for 401/403/404 errors. + + Args: + error (google.api_core.exceptions.GoogleAPICallError): The error to add the cred info. + """ + if error.code not in [ + HTTPStatus.UNAUTHORIZED, + HTTPStatus.FORBIDDEN, + HTTPStatus.NOT_FOUND, + ]: + return + + cred = self._transport._credentials + + # get_cred_info is only available in google-auth>=2.35.0 + if not hasattr(cred, "get_cred_info"): + return + + # ignore the type check since pypy test fails when get_cred_info + # is not available + cred_info = cred.get_cred_info() # type: ignore + if cred_info and hasattr(error._details, "append"): + error._details.append(json.dumps(cred_info)) + + @property + def api_endpoint(self) -> str: + """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, AclConfigServiceTransport, Callable[..., AclConfigServiceTransport] + ] + ] = None, + client_options: Optional[Union[client_options_lib.ClientOptions, dict]] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the acl config service client. + + Args: + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + transport (Optional[Union[str,AclConfigServiceTransport,Callable[..., AclConfigServiceTransport]]]): + The transport to use, or a Callable that constructs and returns a new transport. + If a Callable is given, it will be called with the same set of initialization + arguments as used in the AclConfigServiceTransport constructor. + If set to None, a transport is chosen automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): + Custom options for the client. + + 1. The ``api_endpoint`` property can be used to override the + default endpoint provided by the client when ``transport`` is + not explicitly provided. Only if this property is not set and + ``transport`` was not explicitly provided, the endpoint is + determined by the GOOGLE_API_USE_MTLS_ENDPOINT environment + variable, which have one of the following values: + "always" (always use the default mTLS endpoint), "never" (always + use the default regular endpoint) and "auto" (auto-switch to the + default mTLS endpoint if client certificate is present; this is + the default value). + + 2. If the GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide a client certificate for mTLS transport. If + not provided, the default SSL client certificate will be used if + present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not + set, no client certificate will be used. + + 3. The ``universe_domain`` property can be used to override the + default "googleapis.com" universe. Note that the ``api_endpoint`` + property still takes precedence; and ``universe_domain`` is + currently not supported for mTLS. + + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + """ + self._client_options = client_options + if isinstance(self._client_options, dict): + self._client_options = client_options_lib.from_dict(self._client_options) + if self._client_options is None: + self._client_options = client_options_lib.ClientOptions() + self._client_options = cast( + client_options_lib.ClientOptions, self._client_options + ) + + universe_domain_opt = getattr(self._client_options, "universe_domain", None) + + self._use_client_cert, self._use_mtls_endpoint, self._universe_domain_env = ( + AclConfigServiceClient._read_environment_variables() + ) + self._client_cert_source = AclConfigServiceClient._get_client_cert_source( + self._client_options.client_cert_source, self._use_client_cert + ) + self._universe_domain = AclConfigServiceClient._get_universe_domain( + universe_domain_opt, self._universe_domain_env + ) + self._api_endpoint: str = "" # updated below, depending on `transport` + + # Initialize the universe domain validation. + self._is_universe_domain_valid = False + + if CLIENT_LOGGING_SUPPORTED: # pragma: NO COVER + # Setup logging. + client_logging.initialize_logging() + + 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, AclConfigServiceTransport) + if transport_provided: + # transport is a AclConfigServiceTransport 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(AclConfigServiceTransport, transport) + self._api_endpoint = self._transport.host + + self._api_endpoint = ( + self._api_endpoint + or AclConfigServiceClient._get_api_endpoint( + self._client_options.api_endpoint, + self._client_cert_source, + self._universe_domain, + self._use_mtls_endpoint, + ) + ) + + if not transport_provided: + import google.auth._default # type: ignore + + if api_key_value and hasattr( + google.auth._default, "get_api_key_credentials" + ): + credentials = google.auth._default.get_api_key_credentials( + api_key_value + ) + + transport_init: Union[ + Type[AclConfigServiceTransport], + Callable[..., AclConfigServiceTransport], + ] = ( + AclConfigServiceClient.get_transport_class(transport) + if isinstance(transport, str) or transport is None + else cast(Callable[..., AclConfigServiceTransport], transport) + ) + # initialize with the provided callable or the passed in class + self._transport = transport_init( + credentials=credentials, + credentials_file=self._client_options.credentials_file, + host=self._api_endpoint, + scopes=self._client_options.scopes, + client_cert_source_for_mtls=self._client_cert_source, + quota_project_id=self._client_options.quota_project_id, + client_info=client_info, + always_use_jwt_access=True, + api_audience=self._client_options.api_audience, + ) + + if "async" not in str(self._transport): + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + std_logging.DEBUG + ): # pragma: NO COVER + _LOGGER.debug( + "Created client `google.cloud.discoveryengine_v1beta.AclConfigServiceClient`.", + extra={ + "serviceName": "google.cloud.discoveryengine.v1beta.AclConfigService", + "universeDomain": getattr( + self._transport._credentials, "universe_domain", "" + ), + "credentialsType": f"{type(self._transport._credentials).__module__}.{type(self._transport._credentials).__qualname__}", + "credentialsInfo": getattr( + self.transport._credentials, "get_cred_info", lambda: None + )(), + } + if hasattr(self._transport, "_credentials") + else { + "serviceName": "google.cloud.discoveryengine.v1beta.AclConfigService", + "credentialsType": None, + }, + ) + + def update_acl_config( + self, + request: Optional[ + Union[acl_config_service.UpdateAclConfigRequest, dict] + ] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> acl_config.AclConfig: + r"""Default ACL configuration for use in a location of a + customer's project. Updates will only reflect to new + data stores. Existing data stores will still use the old + value. + + .. 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_acl_config(): + # Create a client + client = discoveryengine_v1beta.AclConfigServiceClient() + + # Initialize request argument(s) + request = discoveryengine_v1beta.UpdateAclConfigRequest( + ) + + # Make the request + response = client.update_acl_config(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.discoveryengine_v1beta.types.UpdateAclConfigRequest, dict]): + The request object. Request message for UpdateAclConfig + 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + google.cloud.discoveryengine_v1beta.types.AclConfig: + Access Control Configuration. + """ + # Create or coerce a protobuf request object. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, acl_config_service.UpdateAclConfigRequest): + request = acl_config_service.UpdateAclConfigRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.update_acl_config] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("acl_config.name", request.acl_config.name),) + ), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + def get_acl_config( + self, + request: Optional[Union[acl_config_service.GetAclConfigRequest, dict]] = None, + *, + name: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> acl_config.AclConfig: + r"""Gets the + [AclConfig][google.cloud.discoveryengine.v1beta.AclConfig]. + + .. 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_acl_config(): + # Create a client + client = discoveryengine_v1beta.AclConfigServiceClient() + + # Initialize request argument(s) + request = discoveryengine_v1beta.GetAclConfigRequest( + name="name_value", + ) + + # Make the request + response = client.get_acl_config(request=request) + + # Handle the response + print(response) + + Args: + request (Union[google.cloud.discoveryengine_v1beta.types.GetAclConfigRequest, dict]): + The request object. Request message for + GetAclConfigRequest method. + name (str): + Required. Resource name of + [AclConfig][google.cloud.discoveryengine.v1beta.AclConfig], + such as ``projects/*/locations/*/aclConfig``. + + If the caller does not have permission to access the + [AclConfig][google.cloud.discoveryengine.v1beta.AclConfig], + regardless of whether or not it exists, a + PERMISSION_DENIED 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + google.cloud.discoveryengine_v1beta.types.AclConfig: + Access Control Configuration. + """ + # 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. + flattened_params = [name] + has_flattened_params = ( + len([param for param in flattened_params if param is not None]) > 0 + ) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, acl_config_service.GetAclConfigRequest): + request = acl_config_service.GetAclConfigRequest(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_acl_config] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request.name),)), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + response = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + def __enter__(self) -> "AclConfigServiceClient": + 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[Union[operations_pb2.ListOperationsRequest, dict]] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + 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 request is None: + request_pb = operations_pb2.ListOperationsRequest() + elif isinstance(request, dict): + request_pb = operations_pb2.ListOperationsRequest(**request) + else: + request_pb = request + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.list_operations] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request_pb.name),)), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + try: + # Send the request. + response = rpc( + request_pb, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + except core_exceptions.GoogleAPICallError as e: + self._add_cred_info_for_auth_errors(e) + raise e + + def get_operation( + self, + request: Optional[Union[operations_pb2.GetOperationRequest, dict]] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + 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 request is None: + request_pb = operations_pb2.GetOperationRequest() + elif isinstance(request, dict): + request_pb = operations_pb2.GetOperationRequest(**request) + else: + request_pb = request + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.get_operation] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request_pb.name),)), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + try: + # Send the request. + response = rpc( + request_pb, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + except core_exceptions.GoogleAPICallError as e: + self._add_cred_info_for_auth_errors(e) + raise e + + def cancel_operation( + self, + request: Optional[Union[operations_pb2.CancelOperationRequest, dict]] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> None: + r"""Starts asynchronous cancellation on a long-running operation. + + The server makes a best effort to cancel the operation, but success + is not guaranteed. If the server doesn't support this method, it returns + `google.rpc.Code.UNIMPLEMENTED`. + + Args: + request (:class:`~.operations_pb2.CancelOperationRequest`): + The request object. Request message for + `CancelOperation` 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + Returns: + None + """ + # 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 request is None: + request_pb = operations_pb2.CancelOperationRequest() + elif isinstance(request, dict): + request_pb = operations_pb2.CancelOperationRequest(**request) + else: + request_pb = request + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._transport._wrapped_methods[self._transport.cancel_operation] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request_pb.name),)), + ) + + # Validate the universe domain. + self._validate_universe_domain() + + # Send the request. + rpc( + request_pb, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + +DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=package_version.__version__ +) + +if hasattr(DEFAULT_CLIENT_INFO, "protobuf_runtime_version"): # pragma: NO COVER + DEFAULT_CLIENT_INFO.protobuf_runtime_version = google.protobuf.__version__ + +__all__ = ("AclConfigServiceClient",) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/acl_config_service/transports/README.rst b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/acl_config_service/transports/README.rst new file mode 100644 index 000000000000..27930d4db5ee --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/acl_config_service/transports/README.rst @@ -0,0 +1,10 @@ + +transport inheritance structure +_______________________________ + +``AclConfigServiceTransport`` is the ABC for all transports. + +- public child ``AclConfigServiceGrpcTransport`` for sync gRPC transport (defined in ``grpc.py``). +- public child ``AclConfigServiceGrpcAsyncIOTransport`` for async gRPC transport (defined in ``grpc_asyncio.py``). +- private child ``_BaseAclConfigServiceRestTransport`` for base REST transport with inner classes ``_BaseMETHOD`` (defined in ``rest_base.py``). +- public child ``AclConfigServiceRestTransport`` for sync REST transport with inner classes ``METHOD`` derived from the parent's corresponding ``_BaseMETHOD`` classes (defined in ``rest.py``). diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/acl_config_service/transports/__init__.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/acl_config_service/transports/__init__.py new file mode 100644 index 000000000000..87322302a120 --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/acl_config_service/transports/__init__.py @@ -0,0 +1,36 @@ +# -*- coding: utf-8 -*- +# Copyright 2026 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 AclConfigServiceTransport +from .grpc import AclConfigServiceGrpcTransport +from .grpc_asyncio import AclConfigServiceGrpcAsyncIOTransport +from .rest import AclConfigServiceRestInterceptor, AclConfigServiceRestTransport + +# Compile a registry of transports. +_transport_registry = OrderedDict() # type: Dict[str, Type[AclConfigServiceTransport]] +_transport_registry["grpc"] = AclConfigServiceGrpcTransport +_transport_registry["grpc_asyncio"] = AclConfigServiceGrpcAsyncIOTransport +_transport_registry["rest"] = AclConfigServiceRestTransport + +__all__ = ( + "AclConfigServiceTransport", + "AclConfigServiceGrpcTransport", + "AclConfigServiceGrpcAsyncIOTransport", + "AclConfigServiceRestTransport", + "AclConfigServiceRestInterceptor", +) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/acl_config_service/transports/base.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/acl_config_service/transports/base.py new file mode 100644 index 000000000000..f62efa912d73 --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/acl_config_service/transports/base.py @@ -0,0 +1,240 @@ +# -*- coding: utf-8 -*- +# Copyright 2026 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 +import google.auth # type: ignore +import google.protobuf +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.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 acl_config, acl_config_service + +DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=package_version.__version__ +) + +if hasattr(DEFAULT_CLIENT_INFO, "protobuf_runtime_version"): # pragma: NO COVER + DEFAULT_CLIENT_INFO.protobuf_runtime_version = google.protobuf.__version__ + + +class AclConfigServiceTransport(abc.ABC): + """Abstract transport class for AclConfigService.""" + + AUTH_SCOPES = ( + "https://www.googleapis.com/auth/cloud-platform", + "https://www.googleapis.com/auth/discoveryengine.readwrite", + "https://www.googleapis.com/auth/discoveryengine.serving.readwrite", + ) + + 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]): Deprecated. A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. This argument will be + removed in the next major version of this library. + 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. + api_audience (Optional[str]): The intended audience for the API calls + to the service that will be set when using certain 3rd party + authentication flows. Audience is typically a resource identifier. + If not set, the host value will be used as a default. + """ + + # Save the scopes. + self._scopes = scopes + if not hasattr(self, "_ignore_credentials"): + self._ignore_credentials: bool = False + + # If no credentials are provided, then determine the appropriate + # defaults. + if credentials and credentials_file: + raise core_exceptions.DuplicateCredentialArgs( + "'credentials_file' and 'credentials' are mutually exclusive" + ) + + if credentials_file is not None: + credentials, _ = google.auth.load_credentials_from_file( + credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + default_scopes=self.AUTH_SCOPES, + ) + elif credentials is None and not self._ignore_credentials: + credentials, _ = google.auth.default( + scopes=scopes, + quota_project_id=quota_project_id, + default_scopes=self.AUTH_SCOPES, + ) + # 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 + + self._wrapped_methods: Dict[Callable, Callable] = {} + + @property + def host(self): + return self._host + + def _prep_wrapped_messages(self, client_info): + # Precompute the wrapped methods. + self._wrapped_methods = { + self.update_acl_config: gapic_v1.method.wrap_method( + self.update_acl_config, + default_timeout=None, + client_info=client_info, + ), + self.get_acl_config: gapic_v1.method.wrap_method( + self.get_acl_config, + default_timeout=None, + client_info=client_info, + ), + self.cancel_operation: gapic_v1.method.wrap_method( + self.cancel_operation, + default_timeout=None, + client_info=client_info, + ), + self.get_operation: gapic_v1.method.wrap_method( + self.get_operation, + default_timeout=None, + client_info=client_info, + ), + self.list_operations: gapic_v1.method.wrap_method( + self.list_operations, + default_timeout=None, + client_info=client_info, + ), + } + + def close(self): + """Closes resources associated with the transport. + + .. warning:: + Only call this method if the transport is NOT shared + with other clients - this may cause errors in other clients! + """ + raise NotImplementedError() + + @property + def update_acl_config( + self, + ) -> Callable[ + [acl_config_service.UpdateAclConfigRequest], + Union[acl_config.AclConfig, Awaitable[acl_config.AclConfig]], + ]: + raise NotImplementedError() + + @property + def get_acl_config( + self, + ) -> Callable[ + [acl_config_service.GetAclConfigRequest], + Union[acl_config.AclConfig, Awaitable[acl_config.AclConfig]], + ]: + 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 cancel_operation( + self, + ) -> Callable[ + [operations_pb2.CancelOperationRequest], + None, + ]: + raise NotImplementedError() + + @property + def kind(self) -> str: + raise NotImplementedError() + + +__all__ = ("AclConfigServiceTransport",) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/acl_config_service/transports/grpc.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/acl_config_service/transports/grpc.py new file mode 100644 index 000000000000..f3649970e6ae --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/acl_config_service/transports/grpc.py @@ -0,0 +1,447 @@ +# -*- coding: utf-8 -*- +# Copyright 2026 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 json +import logging as std_logging +import pickle +import warnings +from typing import Callable, Dict, Optional, Sequence, Tuple, Union + +import google.auth # type: ignore +import google.protobuf.message +import grpc # type: ignore +import proto # type: ignore +from google.api_core import gapic_v1, grpc_helpers +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 +from google.protobuf.json_format import MessageToJson + +from google.cloud.discoveryengine_v1beta.types import acl_config, acl_config_service + +from .base import DEFAULT_CLIENT_INFO, AclConfigServiceTransport + +try: + from google.api_core import client_logging # type: ignore + + CLIENT_LOGGING_SUPPORTED = True # pragma: NO COVER +except ImportError: # pragma: NO COVER + CLIENT_LOGGING_SUPPORTED = False + +_LOGGER = std_logging.getLogger(__name__) + + +class _LoggingClientInterceptor(grpc.UnaryUnaryClientInterceptor): # pragma: NO COVER + def intercept_unary_unary(self, continuation, client_call_details, request): + logging_enabled = CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + std_logging.DEBUG + ) + if logging_enabled: # pragma: NO COVER + request_metadata = client_call_details.metadata + if isinstance(request, proto.Message): + request_payload = type(request).to_json(request) + elif isinstance(request, google.protobuf.message.Message): + request_payload = MessageToJson(request) + else: + request_payload = f"{type(request).__name__}: {pickle.dumps(request)!r}" + + request_metadata = { + key: value.decode("utf-8") if isinstance(value, bytes) else value + for key, value in request_metadata + } + grpc_request = { + "payload": request_payload, + "requestMethod": "grpc", + "metadata": dict(request_metadata), + } + _LOGGER.debug( + f"Sending request for {client_call_details.method}", + extra={ + "serviceName": "google.cloud.discoveryengine.v1beta.AclConfigService", + "rpcName": str(client_call_details.method), + "request": grpc_request, + "metadata": grpc_request["metadata"], + }, + ) + response = continuation(client_call_details, request) + if logging_enabled: # pragma: NO COVER + response_metadata = response.trailing_metadata() + # Convert gRPC metadata `` to list of tuples + metadata = ( + dict([(k, str(v)) for k, v in response_metadata]) + if response_metadata + else None + ) + result = response.result() + if isinstance(result, proto.Message): + response_payload = type(result).to_json(result) + elif isinstance(result, google.protobuf.message.Message): + response_payload = MessageToJson(result) + else: + response_payload = f"{type(result).__name__}: {pickle.dumps(result)!r}" + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response for {client_call_details.method}.", + extra={ + "serviceName": "google.cloud.discoveryengine.v1beta.AclConfigService", + "rpcName": client_call_details.method, + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AclConfigServiceGrpcTransport(AclConfigServiceTransport): + """gRPC backend transport for AclConfigService. + + Service for managing Acl Configuration. + + 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[Union[grpc.Channel, Callable[..., grpc.Channel]]] = None, + api_mtls_endpoint: Optional[str] = None, + client_cert_source: Optional[Callable[[], Tuple[bytes, bytes]]] = None, + ssl_channel_credentials: Optional[grpc.ChannelCredentials] = None, + client_cert_source_for_mtls: Optional[Callable[[], Tuple[bytes, bytes]]] = None, + quota_project_id: Optional[str] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, + api_audience: Optional[str] = None, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to (default: '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 a ``channel`` instance is provided. + credentials_file (Optional[str]): Deprecated. A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if a ``channel`` instance is provided. + This argument will be removed in the next major version of this library. + scopes (Optional(Sequence[str])): A list of scopes. This argument is + ignored if a ``channel`` instance is provided. + channel (Optional[Union[grpc.Channel, Callable[..., grpc.Channel]]]): + A ``Channel`` instance through which to make calls, or a Callable + that constructs and returns one. If set to None, ``self.create_channel`` + is used to create the channel. If a Callable is given, it will be called + with the same arguments as used in ``self.create_channel``. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if a ``channel`` instance is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if a ``channel`` instance or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + api_audience (Optional[str]): The intended audience for the API calls + to the service that will be set when using certain 3rd party + authentication flows. Audience is typically a resource identifier. + If not set, the host value will be used as a default. + + Raises: + google.auth.exceptions.MutualTLSChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn("client_cert_source is deprecated", DeprecationWarning) + + if isinstance(channel, grpc.Channel): + # Ignore credentials if a channel was passed. + credentials = None + self._ignore_credentials = True + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + else: + self._ssl_channel_credentials = SslCredentials().ssl_credentials + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + api_audience=api_audience, + ) + + if not self._grpc_channel: + # initialize with the provided callable or the default channel + channel_init = channel or type(self).create_channel + self._grpc_channel = channel_init( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + self._interceptor = _LoggingClientInterceptor() + self._logged_channel = grpc.intercept_channel( + self._grpc_channel, self._interceptor + ) + + # Wrap messages. This must be done after self._logged_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]): Deprecated. A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is mutually exclusive with credentials. This argument will be + removed in the next major version of this library. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + kwargs (Optional[dict]): Keyword arguments, which are passed to the + channel creation. + Returns: + grpc.Channel: A gRPC channel object. + + Raises: + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + + return grpc_helpers.create_channel( + host, + credentials=credentials, + credentials_file=credentials_file, + quota_project_id=quota_project_id, + default_scopes=cls.AUTH_SCOPES, + scopes=scopes, + default_host=cls.DEFAULT_HOST, + **kwargs, + ) + + @property + def grpc_channel(self) -> grpc.Channel: + """Return the channel designed to connect to this service.""" + return self._grpc_channel + + @property + def update_acl_config( + self, + ) -> Callable[[acl_config_service.UpdateAclConfigRequest], acl_config.AclConfig]: + r"""Return a callable for the update acl config method over gRPC. + + Default ACL configuration for use in a location of a + customer's project. Updates will only reflect to new + data stores. Existing data stores will still use the old + value. + + Returns: + Callable[[~.UpdateAclConfigRequest], + ~.AclConfig]: + 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_acl_config" not in self._stubs: + self._stubs["update_acl_config"] = self._logged_channel.unary_unary( + "/google.cloud.discoveryengine.v1beta.AclConfigService/UpdateAclConfig", + request_serializer=acl_config_service.UpdateAclConfigRequest.serialize, + response_deserializer=acl_config.AclConfig.deserialize, + ) + return self._stubs["update_acl_config"] + + @property + def get_acl_config( + self, + ) -> Callable[[acl_config_service.GetAclConfigRequest], acl_config.AclConfig]: + r"""Return a callable for the get acl config method over gRPC. + + Gets the + [AclConfig][google.cloud.discoveryengine.v1beta.AclConfig]. + + Returns: + Callable[[~.GetAclConfigRequest], + ~.AclConfig]: + 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_acl_config" not in self._stubs: + self._stubs["get_acl_config"] = self._logged_channel.unary_unary( + "/google.cloud.discoveryengine.v1beta.AclConfigService/GetAclConfig", + request_serializer=acl_config_service.GetAclConfigRequest.serialize, + response_deserializer=acl_config.AclConfig.deserialize, + ) + return self._stubs["get_acl_config"] + + def close(self): + self._logged_channel.close() + + @property + def cancel_operation( + self, + ) -> Callable[[operations_pb2.CancelOperationRequest], None]: + r"""Return a callable for the cancel_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 "cancel_operation" not in self._stubs: + self._stubs["cancel_operation"] = self._logged_channel.unary_unary( + "/google.longrunning.Operations/CancelOperation", + request_serializer=operations_pb2.CancelOperationRequest.SerializeToString, + response_deserializer=None, + ) + return self._stubs["cancel_operation"] + + @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._logged_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._logged_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__ = ("AclConfigServiceGrpcTransport",) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/acl_config_service/transports/grpc_asyncio.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/acl_config_service/transports/grpc_asyncio.py new file mode 100644 index 000000000000..28f53fceab7c --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/acl_config_service/transports/grpc_asyncio.py @@ -0,0 +1,494 @@ +# -*- coding: utf-8 -*- +# Copyright 2026 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 inspect +import json +import logging as std_logging +import pickle +import warnings +from typing import Awaitable, Callable, Dict, Optional, Sequence, Tuple, Union + +import google.protobuf.message +import grpc # type: ignore +import proto # type: ignore +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1, grpc_helpers_async +from google.api_core import retry_async as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.grpc import SslCredentials # type: ignore +from google.cloud.location import locations_pb2 # type: ignore +from google.longrunning import operations_pb2 # type: ignore +from google.protobuf.json_format import MessageToJson +from grpc.experimental import aio # type: ignore + +from google.cloud.discoveryengine_v1beta.types import acl_config, acl_config_service + +from .base import DEFAULT_CLIENT_INFO, AclConfigServiceTransport +from .grpc import AclConfigServiceGrpcTransport + +try: + from google.api_core import client_logging # type: ignore + + CLIENT_LOGGING_SUPPORTED = True # pragma: NO COVER +except ImportError: # pragma: NO COVER + CLIENT_LOGGING_SUPPORTED = False + +_LOGGER = std_logging.getLogger(__name__) + + +class _LoggingClientAIOInterceptor( + grpc.aio.UnaryUnaryClientInterceptor +): # pragma: NO COVER + async def intercept_unary_unary(self, continuation, client_call_details, request): + logging_enabled = CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + std_logging.DEBUG + ) + if logging_enabled: # pragma: NO COVER + request_metadata = client_call_details.metadata + if isinstance(request, proto.Message): + request_payload = type(request).to_json(request) + elif isinstance(request, google.protobuf.message.Message): + request_payload = MessageToJson(request) + else: + request_payload = f"{type(request).__name__}: {pickle.dumps(request)!r}" + + request_metadata = { + key: value.decode("utf-8") if isinstance(value, bytes) else value + for key, value in request_metadata + } + grpc_request = { + "payload": request_payload, + "requestMethod": "grpc", + "metadata": dict(request_metadata), + } + _LOGGER.debug( + f"Sending request for {client_call_details.method}", + extra={ + "serviceName": "google.cloud.discoveryengine.v1beta.AclConfigService", + "rpcName": str(client_call_details.method), + "request": grpc_request, + "metadata": grpc_request["metadata"], + }, + ) + response = await continuation(client_call_details, request) + if logging_enabled: # pragma: NO COVER + response_metadata = await response.trailing_metadata() + # Convert gRPC metadata `` to list of tuples + metadata = ( + dict([(k, str(v)) for k, v in response_metadata]) + if response_metadata + else None + ) + result = await response + if isinstance(result, proto.Message): + response_payload = type(result).to_json(result) + elif isinstance(result, google.protobuf.message.Message): + response_payload = MessageToJson(result) + else: + response_payload = f"{type(result).__name__}: {pickle.dumps(result)!r}" + grpc_response = { + "payload": response_payload, + "metadata": metadata, + "status": "OK", + } + _LOGGER.debug( + f"Received response to rpc {client_call_details.method}.", + extra={ + "serviceName": "google.cloud.discoveryengine.v1beta.AclConfigService", + "rpcName": str(client_call_details.method), + "response": grpc_response, + "metadata": grpc_response["metadata"], + }, + ) + return response + + +class AclConfigServiceGrpcAsyncIOTransport(AclConfigServiceTransport): + """gRPC AsyncIO backend transport for AclConfigService. + + Service for managing Acl Configuration. + + 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]): Deprecated. A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. This argument will be + removed in the next major version of this library. + 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[Union[aio.Channel, Callable[..., aio.Channel]]] = None, + api_mtls_endpoint: Optional[str] = None, + client_cert_source: Optional[Callable[[], Tuple[bytes, bytes]]] = None, + ssl_channel_credentials: Optional[grpc.ChannelCredentials] = None, + client_cert_source_for_mtls: Optional[Callable[[], Tuple[bytes, bytes]]] = None, + quota_project_id: Optional[str] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, + api_audience: Optional[str] = None, + ) -> None: + """Instantiate the transport. + + Args: + host (Optional[str]): + The hostname to connect to (default: '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 a ``channel`` instance is provided. + credentials_file (Optional[str]): Deprecated. A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if a ``channel`` instance is provided. + This argument will be removed in the next major version of this library. + scopes (Optional[Sequence[str]]): A optional list of scopes needed for this + service. These are only used when credentials are not specified and + are passed to :func:`google.auth.default`. + channel (Optional[Union[aio.Channel, Callable[..., aio.Channel]]]): + A ``Channel`` instance through which to make calls, or a Callable + that constructs and returns one. If set to None, ``self.create_channel`` + is used to create the channel. If a Callable is given, it will be called + with the same arguments as used in ``self.create_channel``. + api_mtls_endpoint (Optional[str]): Deprecated. The mutual TLS endpoint. + If provided, it overrides the ``host`` argument and tries to create + a mutual TLS channel with client SSL credentials from + ``client_cert_source`` or application default SSL credentials. + client_cert_source (Optional[Callable[[], Tuple[bytes, bytes]]]): + Deprecated. A callback to provide client SSL certificate bytes and + private key bytes, both in PEM format. It is ignored if + ``api_mtls_endpoint`` is None. + ssl_channel_credentials (grpc.ChannelCredentials): SSL credentials + for the grpc channel. It is ignored if a ``channel`` instance is provided. + client_cert_source_for_mtls (Optional[Callable[[], Tuple[bytes, bytes]]]): + A callback to provide client certificate bytes and private key bytes, + both in PEM format. It is used to configure a mutual TLS channel. It is + ignored if a ``channel`` instance or ``ssl_channel_credentials`` is provided. + quota_project_id (Optional[str]): An optional project to use for billing + and quota. + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + always_use_jwt_access (Optional[bool]): Whether self signed JWT should + be used for service account credentials. + api_audience (Optional[str]): The intended audience for the API calls + to the service that will be set when using certain 3rd party + authentication flows. Audience is typically a resource identifier. + If not set, the host value will be used as a default. + + Raises: + google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport + creation failed for any reason. + google.api_core.exceptions.DuplicateCredentialArgs: If both ``credentials`` + and ``credentials_file`` are passed. + """ + self._grpc_channel = None + self._ssl_channel_credentials = ssl_channel_credentials + self._stubs: Dict[str, Callable] = {} + + if api_mtls_endpoint: + warnings.warn("api_mtls_endpoint is deprecated", DeprecationWarning) + if client_cert_source: + warnings.warn("client_cert_source is deprecated", DeprecationWarning) + + if isinstance(channel, aio.Channel): + # Ignore credentials if a channel was passed. + credentials = None + self._ignore_credentials = True + # If a channel was explicitly provided, set it. + self._grpc_channel = channel + self._ssl_channel_credentials = None + else: + if api_mtls_endpoint: + host = api_mtls_endpoint + + # Create SSL credentials with client_cert_source or application + # default SSL credentials. + if client_cert_source: + cert, key = client_cert_source() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + else: + self._ssl_channel_credentials = SslCredentials().ssl_credentials + + else: + if client_cert_source_for_mtls and not ssl_channel_credentials: + cert, key = client_cert_source_for_mtls() + self._ssl_channel_credentials = grpc.ssl_channel_credentials( + certificate_chain=cert, private_key=key + ) + + # The base transport sets the host, credentials and scopes + super().__init__( + host=host, + credentials=credentials, + credentials_file=credentials_file, + scopes=scopes, + quota_project_id=quota_project_id, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + api_audience=api_audience, + ) + + if not self._grpc_channel: + # initialize with the provided callable or the default channel + channel_init = channel or type(self).create_channel + self._grpc_channel = channel_init( + self._host, + # use the credentials which are saved + credentials=self._credentials, + # Set ``credentials_file`` to ``None`` here as + # the credentials that we saved earlier should be used. + credentials_file=None, + scopes=self._scopes, + ssl_credentials=self._ssl_channel_credentials, + quota_project_id=quota_project_id, + options=[ + ("grpc.max_send_message_length", -1), + ("grpc.max_receive_message_length", -1), + ], + ) + + self._interceptor = _LoggingClientAIOInterceptor() + self._grpc_channel._unary_unary_interceptors.append(self._interceptor) + self._logged_channel = self._grpc_channel + self._wrap_with_kind = ( + "kind" in inspect.signature(gapic_v1.method_async.wrap_method).parameters + ) + # Wrap messages. This must be done after self._logged_channel exists + self._prep_wrapped_messages(client_info) + + @property + def grpc_channel(self) -> aio.Channel: + """Create the channel designed to connect to this service. + + This property caches on the instance; repeated calls return + the same channel. + """ + # Return the channel from cache. + return self._grpc_channel + + @property + def update_acl_config( + self, + ) -> Callable[ + [acl_config_service.UpdateAclConfigRequest], Awaitable[acl_config.AclConfig] + ]: + r"""Return a callable for the update acl config method over gRPC. + + Default ACL configuration for use in a location of a + customer's project. Updates will only reflect to new + data stores. Existing data stores will still use the old + value. + + Returns: + Callable[[~.UpdateAclConfigRequest], + Awaitable[~.AclConfig]]: + 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_acl_config" not in self._stubs: + self._stubs["update_acl_config"] = self._logged_channel.unary_unary( + "/google.cloud.discoveryengine.v1beta.AclConfigService/UpdateAclConfig", + request_serializer=acl_config_service.UpdateAclConfigRequest.serialize, + response_deserializer=acl_config.AclConfig.deserialize, + ) + return self._stubs["update_acl_config"] + + @property + def get_acl_config( + self, + ) -> Callable[ + [acl_config_service.GetAclConfigRequest], Awaitable[acl_config.AclConfig] + ]: + r"""Return a callable for the get acl config method over gRPC. + + Gets the + [AclConfig][google.cloud.discoveryengine.v1beta.AclConfig]. + + Returns: + Callable[[~.GetAclConfigRequest], + Awaitable[~.AclConfig]]: + 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_acl_config" not in self._stubs: + self._stubs["get_acl_config"] = self._logged_channel.unary_unary( + "/google.cloud.discoveryengine.v1beta.AclConfigService/GetAclConfig", + request_serializer=acl_config_service.GetAclConfigRequest.serialize, + response_deserializer=acl_config.AclConfig.deserialize, + ) + return self._stubs["get_acl_config"] + + def _prep_wrapped_messages(self, client_info): + """Precompute the wrapped methods, overriding the base class method to use async wrappers.""" + self._wrapped_methods = { + self.update_acl_config: self._wrap_method( + self.update_acl_config, + default_timeout=None, + client_info=client_info, + ), + self.get_acl_config: self._wrap_method( + self.get_acl_config, + default_timeout=None, + client_info=client_info, + ), + self.cancel_operation: self._wrap_method( + self.cancel_operation, + default_timeout=None, + client_info=client_info, + ), + self.get_operation: self._wrap_method( + self.get_operation, + default_timeout=None, + client_info=client_info, + ), + self.list_operations: self._wrap_method( + self.list_operations, + default_timeout=None, + client_info=client_info, + ), + } + + def _wrap_method(self, func, *args, **kwargs): + if self._wrap_with_kind: # pragma: NO COVER + kwargs["kind"] = self.kind + return gapic_v1.method_async.wrap_method(func, *args, **kwargs) + + def close(self): + return self._logged_channel.close() + + @property + def kind(self) -> str: + return "grpc_asyncio" + + @property + def cancel_operation( + self, + ) -> Callable[[operations_pb2.CancelOperationRequest], None]: + r"""Return a callable for the cancel_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 "cancel_operation" not in self._stubs: + self._stubs["cancel_operation"] = self._logged_channel.unary_unary( + "/google.longrunning.Operations/CancelOperation", + request_serializer=operations_pb2.CancelOperationRequest.SerializeToString, + response_deserializer=None, + ) + return self._stubs["cancel_operation"] + + @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._logged_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._logged_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__ = ("AclConfigServiceGrpcAsyncIOTransport",) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/acl_config_service/transports/rest.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/acl_config_service/transports/rest.py new file mode 100644 index 000000000000..4c90dd2644fc --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/acl_config_service/transports/rest.py @@ -0,0 +1,1081 @@ +# -*- coding: utf-8 -*- +# Copyright 2026 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 logging +import warnings +from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple, Union + +import google.protobuf +from google.api_core import exceptions as core_exceptions +from google.api_core import gapic_v1, rest_helpers, rest_streaming +from google.api_core import retry as retries +from google.auth import credentials as ga_credentials # type: ignore +from google.auth.transport.requests import AuthorizedSession # type: ignore +from google.cloud.location import locations_pb2 # type: ignore +from google.longrunning import operations_pb2 # type: ignore +from google.protobuf import json_format +from requests import __version__ as requests_version + +from google.cloud.discoveryengine_v1beta.types import acl_config, acl_config_service + +from .base import DEFAULT_CLIENT_INFO as BASE_DEFAULT_CLIENT_INFO +from .rest_base import _BaseAclConfigServiceRestTransport + +try: + OptionalRetry = Union[retries.Retry, gapic_v1.method._MethodDefault, None] +except AttributeError: # pragma: NO COVER + OptionalRetry = Union[retries.Retry, object, None] # type: ignore + +try: + from google.api_core import client_logging # type: ignore + + CLIENT_LOGGING_SUPPORTED = True # pragma: NO COVER +except ImportError: # pragma: NO COVER + CLIENT_LOGGING_SUPPORTED = False + +_LOGGER = logging.getLogger(__name__) + +DEFAULT_CLIENT_INFO = gapic_v1.client_info.ClientInfo( + gapic_version=BASE_DEFAULT_CLIENT_INFO.gapic_version, + grpc_version=None, + rest_version=f"requests@{requests_version}", +) + +if hasattr(DEFAULT_CLIENT_INFO, "protobuf_runtime_version"): # pragma: NO COVER + DEFAULT_CLIENT_INFO.protobuf_runtime_version = google.protobuf.__version__ + + +class AclConfigServiceRestInterceptor: + """Interceptor for AclConfigService. + + 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 AclConfigServiceRestTransport. + + .. code-block:: python + class MyCustomAclConfigServiceInterceptor(AclConfigServiceRestInterceptor): + def pre_get_acl_config(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_get_acl_config(self, response): + logging.log(f"Received response: {response}") + return response + + def pre_update_acl_config(self, request, metadata): + logging.log(f"Received request: {request}") + return request, metadata + + def post_update_acl_config(self, response): + logging.log(f"Received response: {response}") + return response + + transport = AclConfigServiceRestTransport(interceptor=MyCustomAclConfigServiceInterceptor()) + client = AclConfigServiceClient(transport=transport) + + + """ + + def pre_get_acl_config( + self, + request: acl_config_service.GetAclConfigRequest, + metadata: Sequence[Tuple[str, Union[str, bytes]]], + ) -> Tuple[ + acl_config_service.GetAclConfigRequest, Sequence[Tuple[str, Union[str, bytes]]] + ]: + """Pre-rpc interceptor for get_acl_config + + Override in a subclass to manipulate the request or metadata + before they are sent to the AclConfigService server. + """ + return request, metadata + + def post_get_acl_config( + self, response: acl_config.AclConfig + ) -> acl_config.AclConfig: + """Post-rpc interceptor for get_acl_config + + DEPRECATED. Please use the `post_get_acl_config_with_metadata` + interceptor instead. + + Override in a subclass to read or manipulate the response + after it is returned by the AclConfigService server but before + it is returned to user code. This `post_get_acl_config` interceptor runs + before the `post_get_acl_config_with_metadata` interceptor. + """ + return response + + def post_get_acl_config_with_metadata( + self, + response: acl_config.AclConfig, + metadata: Sequence[Tuple[str, Union[str, bytes]]], + ) -> Tuple[acl_config.AclConfig, Sequence[Tuple[str, Union[str, bytes]]]]: + """Post-rpc interceptor for get_acl_config + + Override in a subclass to read or manipulate the response or metadata after it + is returned by the AclConfigService server but before it is returned to user code. + + We recommend only using this `post_get_acl_config_with_metadata` + interceptor in new development instead of the `post_get_acl_config` interceptor. + When both interceptors are used, this `post_get_acl_config_with_metadata` interceptor runs after the + `post_get_acl_config` interceptor. The (possibly modified) response returned by + `post_get_acl_config` will be passed to + `post_get_acl_config_with_metadata`. + """ + return response, metadata + + def pre_update_acl_config( + self, + request: acl_config_service.UpdateAclConfigRequest, + metadata: Sequence[Tuple[str, Union[str, bytes]]], + ) -> Tuple[ + acl_config_service.UpdateAclConfigRequest, + Sequence[Tuple[str, Union[str, bytes]]], + ]: + """Pre-rpc interceptor for update_acl_config + + Override in a subclass to manipulate the request or metadata + before they are sent to the AclConfigService server. + """ + return request, metadata + + def post_update_acl_config( + self, response: acl_config.AclConfig + ) -> acl_config.AclConfig: + """Post-rpc interceptor for update_acl_config + + DEPRECATED. Please use the `post_update_acl_config_with_metadata` + interceptor instead. + + Override in a subclass to read or manipulate the response + after it is returned by the AclConfigService server but before + it is returned to user code. This `post_update_acl_config` interceptor runs + before the `post_update_acl_config_with_metadata` interceptor. + """ + return response + + def post_update_acl_config_with_metadata( + self, + response: acl_config.AclConfig, + metadata: Sequence[Tuple[str, Union[str, bytes]]], + ) -> Tuple[acl_config.AclConfig, Sequence[Tuple[str, Union[str, bytes]]]]: + """Post-rpc interceptor for update_acl_config + + Override in a subclass to read or manipulate the response or metadata after it + is returned by the AclConfigService server but before it is returned to user code. + + We recommend only using this `post_update_acl_config_with_metadata` + interceptor in new development instead of the `post_update_acl_config` interceptor. + When both interceptors are used, this `post_update_acl_config_with_metadata` interceptor runs after the + `post_update_acl_config` interceptor. The (possibly modified) response returned by + `post_update_acl_config` will be passed to + `post_update_acl_config_with_metadata`. + """ + return response, metadata + + def pre_cancel_operation( + self, + request: operations_pb2.CancelOperationRequest, + metadata: Sequence[Tuple[str, Union[str, bytes]]], + ) -> Tuple[ + operations_pb2.CancelOperationRequest, Sequence[Tuple[str, Union[str, bytes]]] + ]: + """Pre-rpc interceptor for cancel_operation + + Override in a subclass to manipulate the request or metadata + before they are sent to the AclConfigService server. + """ + return request, metadata + + def post_cancel_operation(self, response: None) -> None: + """Post-rpc interceptor for cancel_operation + + Override in a subclass to manipulate the response + after it is returned by the AclConfigService server but before + it is returned to user code. + """ + return response + + def pre_get_operation( + self, + request: operations_pb2.GetOperationRequest, + metadata: Sequence[Tuple[str, Union[str, bytes]]], + ) -> Tuple[ + operations_pb2.GetOperationRequest, Sequence[Tuple[str, Union[str, bytes]]] + ]: + """Pre-rpc interceptor for get_operation + + Override in a subclass to manipulate the request or metadata + before they are sent to the AclConfigService 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 AclConfigService server but before + it is returned to user code. + """ + return response + + def pre_list_operations( + self, + request: operations_pb2.ListOperationsRequest, + metadata: Sequence[Tuple[str, Union[str, bytes]]], + ) -> Tuple[ + operations_pb2.ListOperationsRequest, Sequence[Tuple[str, Union[str, bytes]]] + ]: + """Pre-rpc interceptor for list_operations + + Override in a subclass to manipulate the request or metadata + before they are sent to the AclConfigService 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 AclConfigService server but before + it is returned to user code. + """ + return response + + +@dataclasses.dataclass +class AclConfigServiceRestStub: + _session: AuthorizedSession + _host: str + _interceptor: AclConfigServiceRestInterceptor + + +class AclConfigServiceRestTransport(_BaseAclConfigServiceRestTransport): + """REST backend synchronous transport for AclConfigService. + + Service for managing Acl Configuration. + + 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[AclConfigServiceRestInterceptor] = 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]): Deprecated. A file with credentials that can + be loaded with :func:`google.auth.load_credentials_from_file`. + This argument is ignored if ``channel`` is provided. This argument will be + removed in the next major version of this library. + 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. + interceptor (Optional[AclConfigServiceRestInterceptor]): Interceptor used + to manipulate requests, request metadata, and responses. + api_audience (Optional[str]): The intended audience for the API calls + to the service that will be set when using certain 3rd party + authentication flows. Audience is typically a resource identifier. + If not set, the host value will be used as a default. + """ + # 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 + super().__init__( + host=host, + credentials=credentials, + client_info=client_info, + always_use_jwt_access=always_use_jwt_access, + url_scheme=url_scheme, + 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 AclConfigServiceRestInterceptor() + self._prep_wrapped_messages(client_info) + + class _GetAclConfig( + _BaseAclConfigServiceRestTransport._BaseGetAclConfig, AclConfigServiceRestStub + ): + def __hash__(self): + return hash("AclConfigServiceRestTransport.GetAclConfig") + + @staticmethod + def _get_response( + host, + metadata, + query_params, + session, + timeout, + transcoded_request, + body=None, + ): + uri = transcoded_request["uri"] + method = transcoded_request["method"] + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(session, method)( + "{host}{uri}".format(host=host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + ) + return response + + def __call__( + self, + request: acl_config_service.GetAclConfigRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> acl_config.AclConfig: + r"""Call the get acl config method over HTTP. + + Args: + request (~.acl_config_service.GetAclConfigRequest): + The request object. Request message for + GetAclConfigRequest 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + ~.acl_config.AclConfig: + Access Control Configuration. + """ + + http_options = ( + _BaseAclConfigServiceRestTransport._BaseGetAclConfig._get_http_options() + ) + + request, metadata = self._interceptor.pre_get_acl_config(request, metadata) + transcoded_request = _BaseAclConfigServiceRestTransport._BaseGetAclConfig._get_transcoded_request( + http_options, request + ) + + # Jsonify the query params + query_params = _BaseAclConfigServiceRestTransport._BaseGetAclConfig._get_query_params_json( + transcoded_request + ) + + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + logging.DEBUG + ): # pragma: NO COVER + request_url = "{host}{uri}".format( + host=self._host, uri=transcoded_request["uri"] + ) + method = transcoded_request["method"] + try: + request_payload = type(request).to_json(request) + except: + request_payload = None + http_request = { + "payload": request_payload, + "requestMethod": method, + "requestUrl": request_url, + "headers": dict(metadata), + } + _LOGGER.debug( + f"Sending request for google.cloud.discoveryengine_v1beta.AclConfigServiceClient.GetAclConfig", + extra={ + "serviceName": "google.cloud.discoveryengine.v1beta.AclConfigService", + "rpcName": "GetAclConfig", + "httpRequest": http_request, + "metadata": http_request["headers"], + }, + ) + + # Send the request + response = AclConfigServiceRestTransport._GetAclConfig._get_response( + self._host, + metadata, + query_params, + self._session, + timeout, + transcoded_request, + ) + + # 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 = acl_config.AclConfig() + pb_resp = acl_config.AclConfig.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + + resp = self._interceptor.post_get_acl_config(resp) + response_metadata = [(k, str(v)) for k, v in response.headers.items()] + resp, _ = self._interceptor.post_get_acl_config_with_metadata( + resp, response_metadata + ) + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + logging.DEBUG + ): # pragma: NO COVER + try: + response_payload = acl_config.AclConfig.to_json(response) + except: + response_payload = None + http_response = { + "payload": response_payload, + "headers": dict(response.headers), + "status": response.status_code, + } + _LOGGER.debug( + "Received response for google.cloud.discoveryengine_v1beta.AclConfigServiceClient.get_acl_config", + extra={ + "serviceName": "google.cloud.discoveryengine.v1beta.AclConfigService", + "rpcName": "GetAclConfig", + "metadata": http_response["headers"], + "httpResponse": http_response, + }, + ) + return resp + + class _UpdateAclConfig( + _BaseAclConfigServiceRestTransport._BaseUpdateAclConfig, + AclConfigServiceRestStub, + ): + def __hash__(self): + return hash("AclConfigServiceRestTransport.UpdateAclConfig") + + @staticmethod + def _get_response( + host, + metadata, + query_params, + session, + timeout, + transcoded_request, + body=None, + ): + uri = transcoded_request["uri"] + method = transcoded_request["method"] + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(session, method)( + "{host}{uri}".format(host=host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + data=body, + ) + return response + + def __call__( + self, + request: acl_config_service.UpdateAclConfigRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> acl_config.AclConfig: + r"""Call the update acl config method over HTTP. + + Args: + request (~.acl_config_service.UpdateAclConfigRequest): + The request object. Request message for UpdateAclConfig + 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + ~.acl_config.AclConfig: + Access Control Configuration. + """ + + http_options = _BaseAclConfigServiceRestTransport._BaseUpdateAclConfig._get_http_options() + + request, metadata = self._interceptor.pre_update_acl_config( + request, metadata + ) + transcoded_request = _BaseAclConfigServiceRestTransport._BaseUpdateAclConfig._get_transcoded_request( + http_options, request + ) + + body = _BaseAclConfigServiceRestTransport._BaseUpdateAclConfig._get_request_body_json( + transcoded_request + ) + + # Jsonify the query params + query_params = _BaseAclConfigServiceRestTransport._BaseUpdateAclConfig._get_query_params_json( + transcoded_request + ) + + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + logging.DEBUG + ): # pragma: NO COVER + request_url = "{host}{uri}".format( + host=self._host, uri=transcoded_request["uri"] + ) + method = transcoded_request["method"] + try: + request_payload = type(request).to_json(request) + except: + request_payload = None + http_request = { + "payload": request_payload, + "requestMethod": method, + "requestUrl": request_url, + "headers": dict(metadata), + } + _LOGGER.debug( + f"Sending request for google.cloud.discoveryengine_v1beta.AclConfigServiceClient.UpdateAclConfig", + extra={ + "serviceName": "google.cloud.discoveryengine.v1beta.AclConfigService", + "rpcName": "UpdateAclConfig", + "httpRequest": http_request, + "metadata": http_request["headers"], + }, + ) + + # Send the request + response = AclConfigServiceRestTransport._UpdateAclConfig._get_response( + self._host, + metadata, + query_params, + self._session, + timeout, + transcoded_request, + 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 = acl_config.AclConfig() + pb_resp = acl_config.AclConfig.pb(resp) + + json_format.Parse(response.content, pb_resp, ignore_unknown_fields=True) + + resp = self._interceptor.post_update_acl_config(resp) + response_metadata = [(k, str(v)) for k, v in response.headers.items()] + resp, _ = self._interceptor.post_update_acl_config_with_metadata( + resp, response_metadata + ) + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + logging.DEBUG + ): # pragma: NO COVER + try: + response_payload = acl_config.AclConfig.to_json(response) + except: + response_payload = None + http_response = { + "payload": response_payload, + "headers": dict(response.headers), + "status": response.status_code, + } + _LOGGER.debug( + "Received response for google.cloud.discoveryengine_v1beta.AclConfigServiceClient.update_acl_config", + extra={ + "serviceName": "google.cloud.discoveryengine.v1beta.AclConfigService", + "rpcName": "UpdateAclConfig", + "metadata": http_response["headers"], + "httpResponse": http_response, + }, + ) + return resp + + @property + def get_acl_config( + self, + ) -> Callable[[acl_config_service.GetAclConfigRequest], acl_config.AclConfig]: + # 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._GetAclConfig(self._session, self._host, self._interceptor) # type: ignore + + @property + def update_acl_config( + self, + ) -> Callable[[acl_config_service.UpdateAclConfigRequest], acl_config.AclConfig]: + # 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._UpdateAclConfig(self._session, self._host, self._interceptor) # type: ignore + + @property + def cancel_operation(self): + return self._CancelOperation(self._session, self._host, self._interceptor) # type: ignore + + class _CancelOperation( + _BaseAclConfigServiceRestTransport._BaseCancelOperation, + AclConfigServiceRestStub, + ): + def __hash__(self): + return hash("AclConfigServiceRestTransport.CancelOperation") + + @staticmethod + def _get_response( + host, + metadata, + query_params, + session, + timeout, + transcoded_request, + body=None, + ): + uri = transcoded_request["uri"] + method = transcoded_request["method"] + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(session, method)( + "{host}{uri}".format(host=host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + data=body, + ) + return response + + def __call__( + self, + request: operations_pb2.CancelOperationRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> None: + r"""Call the cancel operation method over HTTP. + + Args: + request (operations_pb2.CancelOperationRequest): + The request object for CancelOperation 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + """ + + http_options = _BaseAclConfigServiceRestTransport._BaseCancelOperation._get_http_options() + + request, metadata = self._interceptor.pre_cancel_operation( + request, metadata + ) + transcoded_request = _BaseAclConfigServiceRestTransport._BaseCancelOperation._get_transcoded_request( + http_options, request + ) + + body = _BaseAclConfigServiceRestTransport._BaseCancelOperation._get_request_body_json( + transcoded_request + ) + + # Jsonify the query params + query_params = _BaseAclConfigServiceRestTransport._BaseCancelOperation._get_query_params_json( + transcoded_request + ) + + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + logging.DEBUG + ): # pragma: NO COVER + request_url = "{host}{uri}".format( + host=self._host, uri=transcoded_request["uri"] + ) + method = transcoded_request["method"] + try: + request_payload = json_format.MessageToJson(request) + except: + request_payload = None + http_request = { + "payload": request_payload, + "requestMethod": method, + "requestUrl": request_url, + "headers": dict(metadata), + } + _LOGGER.debug( + f"Sending request for google.cloud.discoveryengine_v1beta.AclConfigServiceClient.CancelOperation", + extra={ + "serviceName": "google.cloud.discoveryengine.v1beta.AclConfigService", + "rpcName": "CancelOperation", + "httpRequest": http_request, + "metadata": http_request["headers"], + }, + ) + + # Send the request + response = AclConfigServiceRestTransport._CancelOperation._get_response( + self._host, + metadata, + query_params, + self._session, + timeout, + transcoded_request, + 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 self._interceptor.post_cancel_operation(None) + + @property + def get_operation(self): + return self._GetOperation(self._session, self._host, self._interceptor) # type: ignore + + class _GetOperation( + _BaseAclConfigServiceRestTransport._BaseGetOperation, AclConfigServiceRestStub + ): + def __hash__(self): + return hash("AclConfigServiceRestTransport.GetOperation") + + @staticmethod + def _get_response( + host, + metadata, + query_params, + session, + timeout, + transcoded_request, + body=None, + ): + uri = transcoded_request["uri"] + method = transcoded_request["method"] + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(session, method)( + "{host}{uri}".format(host=host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + ) + return response + + def __call__( + self, + request: operations_pb2.GetOperationRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + operations_pb2.Operation: Response from GetOperation method. + """ + + http_options = ( + _BaseAclConfigServiceRestTransport._BaseGetOperation._get_http_options() + ) + + request, metadata = self._interceptor.pre_get_operation(request, metadata) + transcoded_request = _BaseAclConfigServiceRestTransport._BaseGetOperation._get_transcoded_request( + http_options, request + ) + + # Jsonify the query params + query_params = _BaseAclConfigServiceRestTransport._BaseGetOperation._get_query_params_json( + transcoded_request + ) + + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + logging.DEBUG + ): # pragma: NO COVER + request_url = "{host}{uri}".format( + host=self._host, uri=transcoded_request["uri"] + ) + method = transcoded_request["method"] + try: + request_payload = json_format.MessageToJson(request) + except: + request_payload = None + http_request = { + "payload": request_payload, + "requestMethod": method, + "requestUrl": request_url, + "headers": dict(metadata), + } + _LOGGER.debug( + f"Sending request for google.cloud.discoveryengine_v1beta.AclConfigServiceClient.GetOperation", + extra={ + "serviceName": "google.cloud.discoveryengine.v1beta.AclConfigService", + "rpcName": "GetOperation", + "httpRequest": http_request, + "metadata": http_request["headers"], + }, + ) + + # Send the request + response = AclConfigServiceRestTransport._GetOperation._get_response( + self._host, + metadata, + query_params, + self._session, + timeout, + transcoded_request, + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + content = response.content.decode("utf-8") + resp = operations_pb2.Operation() + resp = json_format.Parse(content, resp) + resp = self._interceptor.post_get_operation(resp) + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + logging.DEBUG + ): # pragma: NO COVER + try: + response_payload = json_format.MessageToJson(resp) + except: + response_payload = None + http_response = { + "payload": response_payload, + "headers": dict(response.headers), + "status": response.status_code, + } + _LOGGER.debug( + "Received response for google.cloud.discoveryengine_v1beta.AclConfigServiceAsyncClient.GetOperation", + extra={ + "serviceName": "google.cloud.discoveryengine.v1beta.AclConfigService", + "rpcName": "GetOperation", + "httpResponse": http_response, + "metadata": http_response["headers"], + }, + ) + return resp + + @property + def list_operations(self): + return self._ListOperations(self._session, self._host, self._interceptor) # type: ignore + + class _ListOperations( + _BaseAclConfigServiceRestTransport._BaseListOperations, AclConfigServiceRestStub + ): + def __hash__(self): + return hash("AclConfigServiceRestTransport.ListOperations") + + @staticmethod + def _get_response( + host, + metadata, + query_params, + session, + timeout, + transcoded_request, + body=None, + ): + uri = transcoded_request["uri"] + method = transcoded_request["method"] + headers = dict(metadata) + headers["Content-Type"] = "application/json" + response = getattr(session, method)( + "{host}{uri}".format(host=host, uri=uri), + timeout=timeout, + headers=headers, + params=rest_helpers.flatten_query_params(query_params, strict=True), + ) + return response + + def __call__( + self, + request: operations_pb2.ListOperationsRequest, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Optional[float] = None, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + operations_pb2.ListOperationsResponse: Response from ListOperations method. + """ + + http_options = _BaseAclConfigServiceRestTransport._BaseListOperations._get_http_options() + + request, metadata = self._interceptor.pre_list_operations(request, metadata) + transcoded_request = _BaseAclConfigServiceRestTransport._BaseListOperations._get_transcoded_request( + http_options, request + ) + + # Jsonify the query params + query_params = _BaseAclConfigServiceRestTransport._BaseListOperations._get_query_params_json( + transcoded_request + ) + + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + logging.DEBUG + ): # pragma: NO COVER + request_url = "{host}{uri}".format( + host=self._host, uri=transcoded_request["uri"] + ) + method = transcoded_request["method"] + try: + request_payload = json_format.MessageToJson(request) + except: + request_payload = None + http_request = { + "payload": request_payload, + "requestMethod": method, + "requestUrl": request_url, + "headers": dict(metadata), + } + _LOGGER.debug( + f"Sending request for google.cloud.discoveryengine_v1beta.AclConfigServiceClient.ListOperations", + extra={ + "serviceName": "google.cloud.discoveryengine.v1beta.AclConfigService", + "rpcName": "ListOperations", + "httpRequest": http_request, + "metadata": http_request["headers"], + }, + ) + + # Send the request + response = AclConfigServiceRestTransport._ListOperations._get_response( + self._host, + metadata, + query_params, + self._session, + timeout, + transcoded_request, + ) + + # In case of error, raise the appropriate core_exceptions.GoogleAPICallError exception + # subclass. + if response.status_code >= 400: + raise core_exceptions.from_http_response(response) + + content = response.content.decode("utf-8") + resp = operations_pb2.ListOperationsResponse() + resp = json_format.Parse(content, resp) + resp = self._interceptor.post_list_operations(resp) + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + logging.DEBUG + ): # pragma: NO COVER + try: + response_payload = json_format.MessageToJson(resp) + except: + response_payload = None + http_response = { + "payload": response_payload, + "headers": dict(response.headers), + "status": response.status_code, + } + _LOGGER.debug( + "Received response for google.cloud.discoveryengine_v1beta.AclConfigServiceAsyncClient.ListOperations", + extra={ + "serviceName": "google.cloud.discoveryengine.v1beta.AclConfigService", + "rpcName": "ListOperations", + "httpResponse": http_response, + "metadata": http_response["headers"], + }, + ) + return resp + + @property + def kind(self) -> str: + return "rest" + + def close(self): + self._session.close() + + +__all__ = ("AclConfigServiceRestTransport",) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/acl_config_service/transports/rest_base.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/acl_config_service/transports/rest_base.py new file mode 100644 index 000000000000..3477ffd57809 --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/acl_config_service/transports/rest_base.py @@ -0,0 +1,407 @@ +# -*- coding: utf-8 -*- +# Copyright 2026 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 json # type: ignore +import re +from typing import Any, Callable, Dict, List, Optional, Sequence, Tuple, Union + +from google.api_core import gapic_v1, path_template +from google.cloud.location import locations_pb2 # type: ignore +from google.longrunning import operations_pb2 # type: ignore +from google.protobuf import json_format + +from google.cloud.discoveryengine_v1beta.types import acl_config, acl_config_service + +from .base import DEFAULT_CLIENT_INFO, AclConfigServiceTransport + + +class _BaseAclConfigServiceRestTransport(AclConfigServiceTransport): + """Base REST backend transport for AclConfigService. + + Note: This class is not meant to be used directly. Use its sync and + async sub-classes instead. + + 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[Any] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + always_use_jwt_access: Optional[bool] = False, + url_scheme: str = "https", + api_audience: Optional[str] = None, + ) -> None: + """Instantiate the transport. + Args: + host (Optional[str]): + The hostname to connect to (default: 'discoveryengine.googleapis.com'). + credentials (Optional[Any]): 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. + 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 + 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, + ) + + class _BaseGetAclConfig: + def __hash__(self): # pragma: NO COVER + return NotImplementedError("__hash__ must be implemented.") + + __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 + } + + @staticmethod + def _get_http_options(): + http_options: List[Dict[str, str]] = [ + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/aclConfig}", + }, + ] + return http_options + + @staticmethod + def _get_transcoded_request(http_options, request): + pb_request = acl_config_service.GetAclConfigRequest.pb(request) + transcoded_request = path_template.transcode(http_options, pb_request) + return transcoded_request + + @staticmethod + def _get_query_params_json(transcoded_request): + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + use_integers_for_enums=True, + ) + ) + query_params.update( + _BaseAclConfigServiceRestTransport._BaseGetAclConfig._get_unset_required_fields( + query_params + ) + ) + + query_params["$alt"] = "json;enum-encoding=int" + return query_params + + class _BaseUpdateAclConfig: + def __hash__(self): # pragma: NO COVER + return NotImplementedError("__hash__ must be implemented.") + + __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 + } + + @staticmethod + def _get_http_options(): + http_options: List[Dict[str, str]] = [ + { + "method": "patch", + "uri": "/v1beta/{acl_config.name=projects/*/locations/*/aclConfig}", + "body": "acl_config", + }, + ] + return http_options + + @staticmethod + def _get_transcoded_request(http_options, request): + pb_request = acl_config_service.UpdateAclConfigRequest.pb(request) + transcoded_request = path_template.transcode(http_options, pb_request) + return transcoded_request + + @staticmethod + def _get_request_body_json(transcoded_request): + # Jsonify the request body + + body = json_format.MessageToJson( + transcoded_request["body"], use_integers_for_enums=True + ) + return body + + @staticmethod + def _get_query_params_json(transcoded_request): + query_params = json.loads( + json_format.MessageToJson( + transcoded_request["query_params"], + use_integers_for_enums=True, + ) + ) + query_params.update( + _BaseAclConfigServiceRestTransport._BaseUpdateAclConfig._get_unset_required_fields( + query_params + ) + ) + + query_params["$alt"] = "json;enum-encoding=int" + return query_params + + class _BaseCancelOperation: + def __hash__(self): # pragma: NO COVER + return NotImplementedError("__hash__ must be implemented.") + + @staticmethod + def _get_http_options(): + http_options: List[Dict[str, str]] = [ + { + "method": "post", + "uri": "/v1beta/{name=projects/*/locations/*/collections/*/dataStores/*/branches/*/operations/*}:cancel", + "body": "*", + }, + { + "method": "post", + "uri": "/v1beta/{name=projects/*/locations/*/dataStores/*/branches/*/operations/*}:cancel", + "body": "*", + }, + ] + return http_options + + @staticmethod + def _get_transcoded_request(http_options, request): + request_kwargs = json_format.MessageToDict(request) + transcoded_request = path_template.transcode(http_options, **request_kwargs) + return transcoded_request + + @staticmethod + def _get_request_body_json(transcoded_request): + body = json.dumps(transcoded_request["body"]) + return body + + @staticmethod + def _get_query_params_json(transcoded_request): + query_params = json.loads(json.dumps(transcoded_request["query_params"])) + return query_params + + class _BaseGetOperation: + def __hash__(self): # pragma: NO COVER + return NotImplementedError("__hash__ must be implemented.") + + @staticmethod + def _get_http_options(): + 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/*/assistants/*/agents/*/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/*/evaluations/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/identityMappingStores/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*/sampleQuerySets/*/operations/*}", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/operations/*}", + }, + ] + return http_options + + @staticmethod + def _get_transcoded_request(http_options, request): + request_kwargs = json_format.MessageToDict(request) + transcoded_request = path_template.transcode(http_options, **request_kwargs) + return transcoded_request + + @staticmethod + def _get_query_params_json(transcoded_request): + query_params = json.loads(json.dumps(transcoded_request["query_params"])) + return query_params + + class _BaseListOperations: + def __hash__(self): # pragma: NO COVER + return NotImplementedError("__hash__ must be implemented.") + + @staticmethod + def _get_http_options(): + 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/*/identityMappingStores/*}/operations", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*/locations/*}/operations", + }, + { + "method": "get", + "uri": "/v1beta/{name=projects/*}/operations", + }, + ] + return http_options + + @staticmethod + def _get_transcoded_request(http_options, request): + request_kwargs = json_format.MessageToDict(request) + transcoded_request = path_template.transcode(http_options, **request_kwargs) + return transcoded_request + + @staticmethod + def _get_query_params_json(transcoded_request): + query_params = json.loads(json.dumps(transcoded_request["query_params"])) + return query_params + + +__all__ = ("_BaseAclConfigServiceRestTransport",) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/assistant_service/__init__.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/assistant_service/__init__.py new file mode 100644 index 000000000000..e85f773562fa --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/assistant_service/__init__.py @@ -0,0 +1,22 @@ +# -*- coding: utf-8 -*- +# Copyright 2026 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 AssistantServiceAsyncClient +from .client import AssistantServiceClient + +__all__ = ( + "AssistantServiceClient", + "AssistantServiceAsyncClient", +) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/assistant_service/async_client.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/assistant_service/async_client.py new file mode 100644 index 000000000000..b7417aa3285e --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/assistant_service/async_client.py @@ -0,0 +1,1194 @@ +# -*- coding: utf-8 -*- +# Copyright 2026 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 logging as std_logging +import re +from collections import OrderedDict +from typing import ( + AsyncIterable, + Awaitable, + Callable, + Dict, + Mapping, + MutableMapping, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, +) + +import google.protobuf +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 + +import google.protobuf.field_mask_pb2 as field_mask_pb2 # type: ignore +import google.protobuf.timestamp_pb2 as timestamp_pb2 # type: ignore +from google.cloud.location import locations_pb2 # type: ignore +from google.longrunning import operations_pb2 # type: ignore + +from google.cloud.discoveryengine_v1beta.services.assistant_service import pagers +from google.cloud.discoveryengine_v1beta.types import ( + assist_answer, + assistant, + assistant_service, +) +from google.cloud.discoveryengine_v1beta.types import assistant as gcd_assistant + +from .client import AssistantServiceClient +from .transports.base import DEFAULT_CLIENT_INFO, AssistantServiceTransport +from .transports.grpc_asyncio import AssistantServiceGrpcAsyncIOTransport + +try: + from google.api_core import client_logging # type: ignore + + CLIENT_LOGGING_SUPPORTED = True # pragma: NO COVER +except ImportError: # pragma: NO COVER + CLIENT_LOGGING_SUPPORTED = False + +_LOGGER = std_logging.getLogger(__name__) + + +class AssistantServiceAsyncClient: + """Service for managing Assistant configuration and assisting + users. + """ + + _client: AssistantServiceClient + + # Copy defaults from the synchronous client for use here. + # Note: DEFAULT_ENDPOINT is deprecated. Use _DEFAULT_ENDPOINT_TEMPLATE instead. + DEFAULT_ENDPOINT = AssistantServiceClient.DEFAULT_ENDPOINT + DEFAULT_MTLS_ENDPOINT = AssistantServiceClient.DEFAULT_MTLS_ENDPOINT + _DEFAULT_ENDPOINT_TEMPLATE = AssistantServiceClient._DEFAULT_ENDPOINT_TEMPLATE + _DEFAULT_UNIVERSE = AssistantServiceClient._DEFAULT_UNIVERSE + + assist_answer_path = staticmethod(AssistantServiceClient.assist_answer_path) + parse_assist_answer_path = staticmethod( + AssistantServiceClient.parse_assist_answer_path + ) + assistant_path = staticmethod(AssistantServiceClient.assistant_path) + parse_assistant_path = staticmethod(AssistantServiceClient.parse_assistant_path) + data_store_path = staticmethod(AssistantServiceClient.data_store_path) + parse_data_store_path = staticmethod(AssistantServiceClient.parse_data_store_path) + document_path = staticmethod(AssistantServiceClient.document_path) + parse_document_path = staticmethod(AssistantServiceClient.parse_document_path) + engine_path = staticmethod(AssistantServiceClient.engine_path) + parse_engine_path = staticmethod(AssistantServiceClient.parse_engine_path) + session_path = staticmethod(AssistantServiceClient.session_path) + parse_session_path = staticmethod(AssistantServiceClient.parse_session_path) + template_path = staticmethod(AssistantServiceClient.template_path) + parse_template_path = staticmethod(AssistantServiceClient.parse_template_path) + common_billing_account_path = staticmethod( + AssistantServiceClient.common_billing_account_path + ) + parse_common_billing_account_path = staticmethod( + AssistantServiceClient.parse_common_billing_account_path + ) + common_folder_path = staticmethod(AssistantServiceClient.common_folder_path) + parse_common_folder_path = staticmethod( + AssistantServiceClient.parse_common_folder_path + ) + common_organization_path = staticmethod( + AssistantServiceClient.common_organization_path + ) + parse_common_organization_path = staticmethod( + AssistantServiceClient.parse_common_organization_path + ) + common_project_path = staticmethod(AssistantServiceClient.common_project_path) + parse_common_project_path = staticmethod( + AssistantServiceClient.parse_common_project_path + ) + common_location_path = staticmethod(AssistantServiceClient.common_location_path) + parse_common_location_path = staticmethod( + AssistantServiceClient.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: + AssistantServiceAsyncClient: The constructed client. + """ + sa_info_func = ( + AssistantServiceClient.from_service_account_info.__func__ # type: ignore + ) + return sa_info_func(AssistantServiceAsyncClient, info, *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: + AssistantServiceAsyncClient: The constructed client. + """ + sa_file_func = ( + AssistantServiceClient.from_service_account_file.__func__ # type: ignore + ) + return sa_file_func(AssistantServiceAsyncClient, filename, *args, **kwargs) + + 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 AssistantServiceClient.get_mtls_endpoint_and_cert_source(client_options) # type: ignore + + @property + def transport(self) -> AssistantServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AssistantServiceTransport: The transport used by the client instance. + """ + return self._client.transport + + @property + def api_endpoint(self) -> str: + """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 = AssistantServiceClient.get_transport_class + + def __init__( + self, + *, + credentials: Optional[ga_credentials.Credentials] = None, + transport: Optional[ + Union[ + str, AssistantServiceTransport, Callable[..., AssistantServiceTransport] + ] + ] = "grpc_asyncio", + client_options: Optional[ClientOptions] = None, + client_info: gapic_v1.client_info.ClientInfo = DEFAULT_CLIENT_INFO, + ) -> None: + """Instantiates the assistant service async client. + + Args: + credentials (Optional[google.auth.credentials.Credentials]): The + authorization credentials to attach to requests. These + credentials identify the application to the service; if none + are specified, the client will attempt to ascertain the + credentials from the environment. + transport (Optional[Union[str,AssistantServiceTransport,Callable[..., AssistantServiceTransport]]]): + The transport to use, or a Callable that constructs and returns a new transport to use. + If a Callable is given, it will be called with the same set of initialization + arguments as used in the AssistantServiceTransport constructor. + If set to None, a transport is chosen automatically. + client_options (Optional[Union[google.api_core.client_options.ClientOptions, dict]]): + Custom options for the client. + + 1. The ``api_endpoint`` property can be used to override the + default endpoint provided by the client when ``transport`` is + not explicitly provided. Only if this property is not set and + ``transport`` was not explicitly provided, the endpoint is + determined by the GOOGLE_API_USE_MTLS_ENDPOINT environment + variable, which have one of the following values: + "always" (always use the default mTLS endpoint), "never" (always + use the default regular endpoint) and "auto" (auto-switch to the + default mTLS endpoint if client certificate is present; this is + the default value). + + 2. If the GOOGLE_API_USE_CLIENT_CERTIFICATE environment variable + is "true", then the ``client_cert_source`` property can be used + to provide a client certificate for mTLS transport. If + not provided, the default SSL client certificate will be used if + present. If GOOGLE_API_USE_CLIENT_CERTIFICATE is "false" or not + set, no client certificate will be used. + + 3. The ``universe_domain`` property can be used to override the + default "googleapis.com" universe. Note that ``api_endpoint`` + property still takes precedence; and ``universe_domain`` is + currently not supported for mTLS. + + client_info (google.api_core.gapic_v1.client_info.ClientInfo): + The client info used to send a user-agent string along with + API requests. If ``None``, then default info will be used. + Generally, you only need to set this if you're developing + your own client library. + + Raises: + google.auth.exceptions.MutualTlsChannelError: If mutual TLS transport + creation failed for any reason. + """ + self._client = AssistantServiceClient( + credentials=credentials, + transport=transport, + client_options=client_options, + client_info=client_info, + ) + + if CLIENT_LOGGING_SUPPORTED and _LOGGER.isEnabledFor( + std_logging.DEBUG + ): # pragma: NO COVER + _LOGGER.debug( + "Created client `google.cloud.discoveryengine_v1beta.AssistantServiceAsyncClient`.", + extra={ + "serviceName": "google.cloud.discoveryengine.v1beta.AssistantService", + "universeDomain": getattr( + self._client._transport._credentials, "universe_domain", "" + ), + "credentialsType": f"{type(self._client._transport._credentials).__module__}.{type(self._client._transport._credentials).__qualname__}", + "credentialsInfo": getattr( + self.transport._credentials, "get_cred_info", lambda: None + )(), + } + if hasattr(self._client._transport, "_credentials") + else { + "serviceName": "google.cloud.discoveryengine.v1beta.AssistantService", + "credentialsType": None, + }, + ) + + def stream_assist( + self, + request: Optional[Union[assistant_service.StreamAssistRequest, dict]] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> Awaitable[AsyncIterable[assistant_service.StreamAssistResponse]]: + r"""Assists the user with a query in a streaming fashion. + + .. 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_stream_assist(): + # Create a client + client = discoveryengine_v1beta.AssistantServiceAsyncClient() + + # Initialize request argument(s) + request = discoveryengine_v1beta.StreamAssistRequest( + name="name_value", + ) + + # Make the request + stream = await client.stream_assist(request=request) + + # Handle the response + async for response in stream: + print(response) + + Args: + request (Optional[Union[google.cloud.discoveryengine_v1beta.types.StreamAssistRequest, dict]]): + The request object. Request for the + [AssistantService.StreamAssist][google.cloud.discoveryengine.v1beta.AssistantService.StreamAssist] + 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + AsyncIterable[google.cloud.discoveryengine_v1beta.types.StreamAssistResponse]: + Response for the + [AssistantService.StreamAssist][google.cloud.discoveryengine.v1beta.AssistantService.StreamAssist] + method. + + """ + # Create or coerce a protobuf request object. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, assistant_service.StreamAssistRequest): + request = assistant_service.StreamAssistRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.stream_assist + ] + + # 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 = rpc( + request, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def create_assistant( + self, + request: Optional[Union[assistant_service.CreateAssistantRequest, dict]] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> assistant.Assistant: + r"""Creates an + [Assistant][google.cloud.discoveryengine.v1beta.Assistant]. + + .. 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_assistant(): + # Create a client + client = discoveryengine_v1beta.AssistantServiceAsyncClient() + + # Initialize request argument(s) + assistant = discoveryengine_v1beta.Assistant() + assistant.display_name = "display_name_value" + + request = discoveryengine_v1beta.CreateAssistantRequest( + parent="parent_value", + assistant=assistant, + assistant_id="assistant_id_value", + ) + + # Make the request + response = await client.create_assistant(request=request) + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.discoveryengine_v1beta.types.CreateAssistantRequest, dict]]): + The request object. Request for the + [AssistantService.CreateAssistant][google.cloud.discoveryengine.v1beta.AssistantService.CreateAssistant] + 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + google.cloud.discoveryengine_v1beta.types.Assistant: + Discovery Engine Assistant resource. + """ + # Create or coerce a protobuf request object. + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, assistant_service.CreateAssistantRequest): + request = assistant_service.CreateAssistantRequest(request) + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.create_assistant + ] + + # 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_assistant( + self, + request: Optional[Union[assistant_service.DeleteAssistantRequest, dict]] = None, + *, + name: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> None: + r"""Deletes an + [Assistant][google.cloud.discoveryengine.v1beta.Assistant]. + + .. 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_assistant(): + # Create a client + client = discoveryengine_v1beta.AssistantServiceAsyncClient() + + # Initialize request argument(s) + request = discoveryengine_v1beta.DeleteAssistantRequest( + name="name_value", + ) + + # Make the request + await client.delete_assistant(request=request) + + Args: + request (Optional[Union[google.cloud.discoveryengine_v1beta.types.DeleteAssistantRequest, dict]]): + The request object. Request message for the + [AssistantService.DeleteAssistant][google.cloud.discoveryengine.v1beta.AssistantService.DeleteAssistant] + method. + name (:class:`str`): + Required. Resource name of + [Assistant][google.cloud.discoveryengine.v1beta.Assistant]. + Format: + ``projects/{project}/locations/{location}/collections/{collection}/engines/{engine}/assistants/{assistant}`` + + If the caller does not have permission to delete the + [Assistant][google.cloud.discoveryengine.v1beta.Assistant], + regardless of whether or not it exists, a + PERMISSION_DENIED error is returned. + + If the + [Assistant][google.cloud.discoveryengine.v1beta.Assistant] + to delete 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + """ + # 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. + flattened_params = [name] + has_flattened_params = ( + len([param for param in flattened_params if param is not None]) > 0 + ) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, assistant_service.DeleteAssistantRequest): + request = assistant_service.DeleteAssistantRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if name is not None: + request.name = name + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.delete_assistant + ] + + # 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_assistant( + self, + request: Optional[Union[assistant_service.UpdateAssistantRequest, dict]] = None, + *, + assistant: Optional[gcd_assistant.Assistant] = 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, Union[str, bytes]]] = (), + ) -> gcd_assistant.Assistant: + r"""Updates an + [Assistant][google.cloud.discoveryengine.v1beta.Assistant] + + .. 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_assistant(): + # Create a client + client = discoveryengine_v1beta.AssistantServiceAsyncClient() + + # Initialize request argument(s) + assistant = discoveryengine_v1beta.Assistant() + assistant.display_name = "display_name_value" + + request = discoveryengine_v1beta.UpdateAssistantRequest( + assistant=assistant, + ) + + # Make the request + response = await client.update_assistant(request=request) + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.discoveryengine_v1beta.types.UpdateAssistantRequest, dict]]): + The request object. Request message for the + [AssistantService.UpdateAssistant][google.cloud.discoveryengine.v1beta.AssistantService.UpdateAssistant] + method. + assistant (:class:`google.cloud.discoveryengine_v1beta.types.Assistant`): + Required. The + [Assistant][google.cloud.discoveryengine.v1beta.Assistant] + to update. + + The + [Assistant][google.cloud.discoveryengine.v1beta.Assistant]'s + ``name`` field is used to identify the + [Assistant][google.cloud.discoveryengine.v1beta.Assistant] + to update. Format: + ``projects/{project}/locations/{location}/collections/{collection}/engines/{engine}/assistants/{assistant}`` + + If the caller does not have permission to update the + [Assistant][google.cloud.discoveryengine.v1beta.Assistant], + regardless of whether or not it exists, a + PERMISSION_DENIED error is returned. + + If the + [Assistant][google.cloud.discoveryengine.v1beta.Assistant] + to update does not exist, a NOT_FOUND error is returned. + + This corresponds to the ``assistant`` field + on the ``request`` instance; if ``request`` is provided, this + should not be set. + update_mask (:class:`google.protobuf.field_mask_pb2.FieldMask`): + The list of fields to update. + 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + google.cloud.discoveryengine_v1beta.types.Assistant: + Discovery Engine Assistant resource. + """ + # 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. + flattened_params = [assistant, update_mask] + has_flattened_params = ( + len([param for param in flattened_params if param is not None]) > 0 + ) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, assistant_service.UpdateAssistantRequest): + request = assistant_service.UpdateAssistantRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if assistant is not None: + request.assistant = assistant + if update_mask is not None: + request.update_mask = update_mask + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.update_assistant + ] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata( + (("assistant.name", request.assistant.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_assistant( + self, + request: Optional[Union[assistant_service.GetAssistantRequest, dict]] = None, + *, + name: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> assistant.Assistant: + r"""Gets an + [Assistant][google.cloud.discoveryengine.v1beta.Assistant]. + + .. 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_assistant(): + # Create a client + client = discoveryengine_v1beta.AssistantServiceAsyncClient() + + # Initialize request argument(s) + request = discoveryengine_v1beta.GetAssistantRequest( + name="name_value", + ) + + # Make the request + response = await client.get_assistant(request=request) + + # Handle the response + print(response) + + Args: + request (Optional[Union[google.cloud.discoveryengine_v1beta.types.GetAssistantRequest, dict]]): + The request object. Request message for the + [AssistantService.GetAssistant][google.cloud.discoveryengine.v1beta.AssistantService.GetAssistant] + method. + name (:class:`str`): + Required. Resource name of + [Assistant][google.cloud.discoveryengine.v1beta.Assistant]. + Format: + ``projects/{project}/locations/{location}/collections/{collection}/engines/{engine}/assistants/{assistant}`` + + 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + google.cloud.discoveryengine_v1beta.types.Assistant: + Discovery Engine Assistant resource. + """ + # 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. + flattened_params = [name] + has_flattened_params = ( + len([param for param in flattened_params if param is not None]) > 0 + ) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, assistant_service.GetAssistantRequest): + request = assistant_service.GetAssistantRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if name is not None: + request.name = name + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.get_assistant + ] + + # 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_assistants( + self, + request: Optional[Union[assistant_service.ListAssistantsRequest, dict]] = None, + *, + parent: Optional[str] = None, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> pagers.ListAssistantsAsyncPager: + r"""Lists all + [Assistant][google.cloud.discoveryengine.v1beta.Assistant]s + under an [Engine][google.cloud.discoveryengine.v1beta.Engine]. + + .. 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_assistants(): + # Create a client + client = discoveryengine_v1beta.AssistantServiceAsyncClient() + + # Initialize request argument(s) + request = discoveryengine_v1beta.ListAssistantsRequest( + parent="parent_value", + ) + + # Make the request + page_result = client.list_assistants(request=request) + + # Handle the response + async for response in page_result: + print(response) + + Args: + request (Optional[Union[google.cloud.discoveryengine_v1beta.types.ListAssistantsRequest, dict]]): + The request object. Request message for the + [AssistantService.ListAssistants][google.cloud.discoveryengine.v1beta.AssistantService.ListAssistants] + method. + parent (:class:`str`): + Required. The parent resource name. Format: + ``projects/{project}/locations/{location}/collections/{collection}/engines/{engine}`` + + 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + + Returns: + google.cloud.discoveryengine_v1beta.services.assistant_service.pagers.ListAssistantsAsyncPager: + Response message for the + [AssistantService.ListAssistants][google.cloud.discoveryengine.v1beta.AssistantService.ListAssistants] + 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. + flattened_params = [parent] + has_flattened_params = ( + len([param for param in flattened_params if param is not None]) > 0 + ) + if request is not None and has_flattened_params: + raise ValueError( + "If the `request` argument is set, then none of " + "the individual field arguments should be set." + ) + + # - Use the request object if provided (there's no risk of modifying the input as + # there are no flattened fields), or create one. + if not isinstance(request, assistant_service.ListAssistantsRequest): + request = assistant_service.ListAssistantsRequest(request) + + # If we have keyword arguments corresponding to fields on the + # request, apply these. + if parent is not None: + request.parent = parent + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self._client._transport._wrapped_methods[ + self._client._transport.list_assistants + ] + + # 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.ListAssistantsAsyncPager( + method=rpc, + request=request, + response=response, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def list_operations( + self, + request: Optional[Union[operations_pb2.ListOperationsRequest, dict]] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + 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 request is None: + request_pb = operations_pb2.ListOperationsRequest() + elif isinstance(request, dict): + request_pb = operations_pb2.ListOperationsRequest(**request) + else: + request_pb = request + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self.transport._wrapped_methods[self._client._transport.list_operations] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request_pb.name),)), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request_pb, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def get_operation( + self, + request: Optional[Union[operations_pb2.GetOperationRequest, dict]] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + 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 request is None: + request_pb = operations_pb2.GetOperationRequest() + elif isinstance(request, dict): + request_pb = operations_pb2.GetOperationRequest(**request) + else: + request_pb = request + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self.transport._wrapped_methods[self._client._transport.get_operation] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request_pb.name),)), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + response = await rpc( + request_pb, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + # Done; return the response. + return response + + async def cancel_operation( + self, + request: Optional[Union[operations_pb2.CancelOperationRequest, dict]] = None, + *, + retry: OptionalRetry = gapic_v1.method.DEFAULT, + timeout: Union[float, object] = gapic_v1.method.DEFAULT, + metadata: Sequence[Tuple[str, Union[str, bytes]]] = (), + ) -> None: + r"""Starts asynchronous cancellation on a long-running operation. + + The server makes a best effort to cancel the operation, but success + is not guaranteed. If the server doesn't support this method, it returns + `google.rpc.Code.UNIMPLEMENTED`. + + Args: + request (:class:`~.operations_pb2.CancelOperationRequest`): + The request object. Request message for + `CancelOperation` 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, Union[str, bytes]]]): Key/value pairs which should be + sent along with the request as metadata. Normally, each value must be of type `str`, + but for metadata keys ending with the suffix `-bin`, the corresponding values must + be of type `bytes`. + Returns: + None + """ + # 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 request is None: + request_pb = operations_pb2.CancelOperationRequest() + elif isinstance(request, dict): + request_pb = operations_pb2.CancelOperationRequest(**request) + else: + request_pb = request + + # Wrap the RPC method; this adds retry and timeout information, + # and friendly error handling. + rpc = self.transport._wrapped_methods[self._client._transport.cancel_operation] + + # Certain fields should be provided within the metadata header; + # add these here. + metadata = tuple(metadata) + ( + gapic_v1.routing_header.to_grpc_metadata((("name", request_pb.name),)), + ) + + # Validate the universe domain. + self._client._validate_universe_domain() + + # Send the request. + await rpc( + request_pb, + retry=retry, + timeout=timeout, + metadata=metadata, + ) + + async def __aenter__(self) -> "AssistantServiceAsyncClient": + 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__ +) + +if hasattr(DEFAULT_CLIENT_INFO, "protobuf_runtime_version"): # pragma: NO COVER + DEFAULT_CLIENT_INFO.protobuf_runtime_version = google.protobuf.__version__ + + +__all__ = ("AssistantServiceAsyncClient",) diff --git a/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/assistant_service/client.py b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/assistant_service/client.py new file mode 100644 index 000000000000..e192f65bff8a --- /dev/null +++ b/packages/google-cloud-discoveryengine/google/cloud/discoveryengine_v1beta/services/assistant_service/client.py @@ -0,0 +1,1762 @@ +# -*- coding: utf-8 -*- +# Copyright 2026 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 json +import logging as std_logging +import os +import re +import warnings +from collections import OrderedDict +from http import HTTPStatus +from typing import ( + Callable, + Dict, + Iterable, + Mapping, + MutableMapping, + MutableSequence, + Optional, + Sequence, + Tuple, + Type, + Union, + cast, +) + +import google.protobuf +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 + +try: + from google.api_core import client_logging # type: ignore + + CLIENT_LOGGING_SUPPORTED = True # pragma: NO COVER +except ImportError: # pragma: NO COVER + CLIENT_LOGGING_SUPPORTED = False + +_LOGGER = std_logging.getLogger(__name__) + +import google.protobuf.field_mask_pb2 as field_mask_pb2 # type: ignore +import google.protobuf.timestamp_pb2 as timestamp_pb2 # type: ignore +from google.cloud.location import locations_pb2 # type: ignore +from google.longrunning import operations_pb2 # type: ignore + +from google.cloud.discoveryengine_v1beta.services.assistant_service import pagers +from google.cloud.discoveryengine_v1beta.types import ( + assist_answer, + assistant, + assistant_service, +) +from google.cloud.discoveryengine_v1beta.types import assistant as gcd_assistant + +from .transports.base import DEFAULT_CLIENT_INFO, AssistantServiceTransport +from .transports.grpc import AssistantServiceGrpcTransport +from .transports.grpc_asyncio import AssistantServiceGrpcAsyncIOTransport +from .transports.rest import AssistantServiceRestTransport + + +class AssistantServiceClientMeta(type): + """Metaclass for the AssistantService 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[AssistantServiceTransport]] + _transport_registry["grpc"] = AssistantServiceGrpcTransport + _transport_registry["grpc_asyncio"] = AssistantServiceGrpcAsyncIOTransport + _transport_registry["rest"] = AssistantServiceRestTransport + + def get_transport_class( + cls, + label: Optional[str] = None, + ) -> Type[AssistantServiceTransport]: + """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 AssistantServiceClient(metaclass=AssistantServiceClientMeta): + """Service for managing Assistant configuration and assisting + users. + """ + + @staticmethod + def _get_default_mtls_endpoint(api_endpoint) -> Optional[str]: + """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: + Optional[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) + if m is None: + # Could not parse api_endpoint; return as-is. + return 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" + + @staticmethod + def _use_client_cert_effective(): + """Returns whether client certificate should be used for mTLS if the + google-auth version supports should_use_client_cert automatic mTLS enablement. + + Alternatively, read from the GOOGLE_API_USE_CLIENT_CERTIFICATE env var. + + Returns: + bool: whether client certificate should be used for mTLS + Raises: + ValueError: (If using a version of google-auth without should_use_client_cert and + GOOGLE_API_USE_CLIENT_CERTIFICATE is set to an unexpected value.) + """ + # check if google-auth version supports should_use_client_cert for automatic mTLS enablement + if hasattr(mtls, "should_use_client_cert"): # pragma: NO COVER + return mtls.should_use_client_cert() + else: # pragma: NO COVER + # if unsupported, fallback to reading from env var + use_client_cert_str = os.getenv( + "GOOGLE_API_USE_CLIENT_CERTIFICATE", "false" + ).lower() + if use_client_cert_str not in ("true", "false"): + raise ValueError( + "Environment variable `GOOGLE_API_USE_CLIENT_CERTIFICATE` must be" + " either `true` or `false`" + ) + return use_client_cert_str == "true" + + @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: + AssistantServiceClient: 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: + AssistantServiceClient: 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) -> AssistantServiceTransport: + """Returns the transport used by the client instance. + + Returns: + AssistantServiceTransport: The transport used by the client + instance. + """ + return self._transport + + @staticmethod + def assist_answer_path( + project: str, + location: str, + collection: str, + engine: str, + session: str, + assist_answer: str, + ) -> str: + """Returns a fully-qualified assist_answer string.""" + return "projects/{project}/locations/{location}/collections/{collection}/engines/{engine}/sessions/{session}/assistAnswers/{assist_answer}".format( + project=project, + location=location, + collection=collection, + engine=engine, + session=session, + assist_answer=assist_answer, + ) + + @staticmethod + def parse_assist_answer_path(path: str) -> Dict[str, str]: + """Parses a assist_answer path into its component segments.""" + m = re.match( + r"^projects/(?P.+?)/locations/(?P.+?)/collections/(?P.+?)/engines/(?P.+?)/sessions/(?P.+?)/assistAnswers/(?P.+?)$", + path, + ) + return m.groupdict() if m else {} + + @staticmethod + def assistant_path( + project: str, + location: str, + collection: str, + engine: str, + assistant: str, + ) -> str: + """Returns a fully-qualified assistant string.""" + return "projects/{project}/locations/{location}/collections/{collection}/engines/{engine}/assistants/{assistant}".format( + project=project, + location=location, + collection=collection, + engine=engine, + assistant=assistant, + ) + + @staticmethod + def parse_assistant_path(path: str) -> Dict[str, str]: + """Parses a assistant path into its component segments.""" + m = re.match( + r"^projects/(?P.+?)/locations/(?P.+?)/collections/(?P.+?)/engines/(?P.+?)/assistants/(?P.+?)$", + path, + ) + 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, + 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 engine_path( + project: str, + location: str, + collection: str, + engine: str, + ) -> str: + """Returns a fully-qualified engine string.""" + return "projects/{project}/locations/{location}/collections/{collection}/engines/{engine}".format( + project=project, + location=location, + collection=collection, + engine=engine, + ) + + @staticmethod + def parse_engine_path(path: str) -> Dict[str, str]: + """Parses a engine path into its component segments.""" + m = re.match( + r"^projects/(?P.+?)/locations/(?P.+?)/collections/(?P.+?)/engines/(?P.+?)$", + path, + ) + 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 template_path( + project: str, + location: str, + template: str, + ) -> str: + """Returns a fully-qualified template string.""" + return "projects/{project}/locations/{location}/templates/{template}".format( + project=project, + location=location, + template=template, + ) + + @staticmethod + def parse_template_path(path: str) -> Dict[str, str]: + """Parses a template path into its component segments.""" + m = re.match( + r"^projects/(?P.+?)/locations/(?P.+?)/templates/(?P